Java 为什么上传到 S3 的文件的内容类型为 application/octet-stream 除非我将文件命名为 .html
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/30706218/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Why does file uploaded to S3 have content type application/octet-stream unless i name the file .html
提问by Paul Taylor
Even though I set content type to text/html it ends up as application/octet-stream on S3.
即使我将内容类型设置为 text/html,它最终还是在 S3 上作为 application/octet-stream。
ByteArrayInputStream contentsAsStream = new ByteArrayInputStream(contentAsBytes);
ObjectMetadata md = new ObjectMetadata();
md.setContentLength(contentAsBytes.length);
md.setContentType("text/html");
s3.putObject(new PutObjectRequest(ARTIST_BUCKET_NAME, artistId, contentsAsStream, md));
If however I name the file so that it ends up with .html
但是,如果我将文件命名为以 .html 结尾
s3.putObject(new PutObjectRequest(ARTIST_BUCKET_NAME, artistId + ".html", contentsAsStream, md));
then it works.
那么它的工作原理。
Is my md object just being ignored ? How can I get round this programmatically as over time I need to upload thousands of files so cannot just go into S3 UI and manually fix the contentType.
我的 md 对象只是被忽略了吗?我怎样才能以编程方式解决这个问题,因为随着时间的推移,我需要上传数千个文件,所以不能只进入 S3 UI 并手动修复 contentType。
回答by Tim
It seemsthat
这似乎是
When uploading files, the AWS S3 Java client will attempt to determine the correct content type if one hasn't been set yet. Users are responsible for ensuring a suitable content type is set when uploading streams. If no content type is provided and cannot be determined by the filename, the default content type, "application/octet-stream", will be used.
上传文件时,AWS S3 Java 客户端将尝试确定正确的内容类型(如果尚未设置)。用户有责任确保在上传流时设置合适的内容类型。如果未提供内容类型且无法由文件名确定,则将使用默认内容类型“application/octet-stream”。
Giving the file a .html extension provides a way to set the correct type.
给文件一个 .html 扩展名提供了一种设置正确类型的方法。
According to the examples I've been looking at, the code you show shouldbe doing what you want to do. :/
根据我一直在查看的示例,您展示的代码应该做您想做的事情。:/
回答by Raniz
You must be doing something else in your code. I just tried your code example using the 1.9.6 S3 SDK and the file gets the "text/html" content type.
您必须在代码中执行其他操作。我刚刚使用 1.9.6 S3 SDK 尝试了您的代码示例,并且该文件获得了“text/html”内容类型。
Here's the exact (Groovy) code:
这是确切的(Groovy)代码:
class S3Test {
static void main(String[] args) {
def s3 = new AmazonS3Client()
def random = new Random()
def bucketName = "raniz-playground"
def keyName = "content-type-test"
byte[] contentAsBytes = new byte[1024]
random.nextBytes(contentAsBytes)
ByteArrayInputStream contentsAsStream = new ByteArrayInputStream(contentAsBytes);
ObjectMetadata md = new ObjectMetadata();
md.setContentLength(contentAsBytes.length);
md.setContentType("text/html");
s3.putObject(new PutObjectRequest(bucketName, keyName, contentsAsStream, md))
def object = s3.getObject(bucketName, keyName)
println(object.objectMetadata.contentType)
object.close()
}
}
The program prints
程序打印
text/html
文本/html
And the S3 metadata says the same:
S3 元数据也有同样的说法:
Here are the communication sent over the net (courtesy of Apache HTTP Commons debug logging):
以下是通过网络发送的通信(由 Apache HTTP Commons 调试日志提供):
>> PUT /content-type-test HTTP/1.1
>> Host: raniz-playground.s3.amazonaws.com
>> Authorization: AWS <nope>
>> User-Agent: aws-sdk-java/1.9.6 Linux/3.2.0-84-generic Java_HotSpot(TM)_64-Bit_Server_VM/25.45-b02/1.8.0_45
>> Date: Fri, 12 Jun 2015 02:11:16 GMT
>> Content-Type: text/html
>> Content-Length: 1024
>> Connection: Keep-Alive
>> Expect: 100-continue
<< HTTP/1.1 200 OK
<< x-amz-id-2: mOsmhYGkW+SxipF6S2+CnmiqOhwJ62WfWUkmZk4zU3rzkWCEH9P/bT1hUz27apmO
<< x-amz-request-id: 8706AE3BE8597644
<< Date: Fri, 12 Jun 2015 02:11:23 GMT
<< ETag: "6c53debeb28f1d12f7ad388b27c9036d"
<< Content-Length: 0
<< Server: AmazonS3
>> GET /content-type-test HTTP/1.1
>> Host: raniz-playground.s3.amazonaws.com
>> Authorization: AWS <nope>
>> User-Agent: aws-sdk-java/1.9.6 Linux/3.2.0-84-generic Java_HotSpot(TM)_64-Bit_Server_VM/25.45-b02/1.8.0_45
>> Date: Fri, 12 Jun 2015 02:11:23 GMT
>> Content-Type: application/x-www-form-urlencoded; charset=utf-8
>> Connection: Keep-Alive
<< HTTP/1.1 200 OK
<< x-amz-id-2: 9U1CQ8yIYBKYyadKi4syaAsr+7BV76Q+5UAGj2w1zDiPC2qZN0NzUCQNv6pWGu7n
<< x-amz-request-id: 6777433366DB6436
<< Date: Fri, 12 Jun 2015 02:11:24 GMT
<< Last-Modified: Fri, 12 Jun 2015 02:11:23 GMT
<< ETag: "6c53debeb28f1d12f7ad388b27c9036d"
<< Accept-Ranges: bytes
<< Content-Type: text/html
<< Content-Length: 1024
<< Server: AmazonS3
And this is also the behaviour that looking at the source codeshows us - if you set the content type the SDK won't override it.
这也是查看源代码向我们展示的行为- 如果您设置内容类型,SDK 将不会覆盖它。
回答by crigore
Do you have any Override on the default mime content on your S3 account? Look at this link to see how to check it: How to override default Content Types.
您对 S3 帐户上的默认 mime 内容有任何覆盖吗?查看此链接以了解如何检查它:How to override default Content Types。
Anyway, it looks like your S3 client fails to determine the correct mime-type by the content of the file, so it relies on the extension. octet-stream is the widely used default content mime type when a browser/servlet can't determine the mimetype: Is there any default mime type?
无论如何,看起来您的 S3 客户端无法通过文件内容确定正确的 MIME 类型,因此它依赖于扩展名。当浏览器/servlet 无法确定 mimetype 时,octet-stream 是广泛使用的默认内容 mime 类型:是否有任何默认 mime 类型?
回答by Levent Divilioglu
Because you have to set content type at the end just before sending, using the putObject method;
因为您必须在发送前最后设置内容类型,使用 putObject 方法;
ObjectMetadata md = new ObjectMetadata();
InputStream myInputStream = new ByteArrayInputStream(bFile);
md.setContentLength(bFile.length);
md.setContentType("text/html");
md.setContentEncoding("UTF-8");
s3client.putObject(new PutObjectRequest(bucketName, keyName, myInputStream, md));
And after upload, content type is set as "text/html"
上传后,内容类型设置为“ text/html”
Here is a working dummy code, check that out, I've just tried and it's working;
这是一个有效的虚拟代码,检查一下,我刚刚尝试过并且可以正常工作;
public class TestAWS {
//TEST
private static String bucketName = "whateverBucket";
public static void main(String[] args) throws Exception {
BasicAWSCredentials awsCreds = new BasicAWSCredentials("whatever", "whatever");
AmazonS3 s3client = new AmazonS3Client(awsCreds);
try
{
String uploadFileName = "D:\try.txt";
String keyName = "newFile.txt";
System.out.println("Uploading a new object to S3 from a file\n");
File file = new File(uploadFileName);
//bFile will be the placeholder of file bytes
byte[] bFile = new byte[(int) file.length()];
FileInputStream fileInputStream=null;
//convert file into array of bytes
fileInputStream = new FileInputStream(file);
fileInputStream.read(bFile);
fileInputStream.close();
ObjectMetadata md = new ObjectMetadata();
InputStream myInputStream = new ByteArrayInputStream(bFile);
md.setContentLength(bFile.length);
md.setContentType("text/html");
md.setContentEncoding("UTF-8");
s3client.putObject(new PutObjectRequest(bucketName, keyName, myInputStream, md));
} catch (AmazonServiceException ase)
{
System.out.println("Caught an AmazonServiceException, which "
+ "means your request made it "
+ "to Amazon S3, but was rejected with an error response"
+ " for some reason.");
System.out.println("Error Message: " + ase.getMessage());
System.out.println("HTTP Status Code: " + ase.getStatusCode());
System.out.println("AWS Error Code: " + ase.getErrorCode());
System.out.println("Error Type: " + ase.getErrorType());
System.out.println("Request ID: " + ase.getRequestId());
} catch (AmazonClientException ace)
{
System.out.println("Caught an AmazonClientException, which "
+ "means the client encountered "
+ "an internal error while trying to "
+ "communicate with S3, "
+ "such as not being able to access the network.");
System.out.println("Error Message: " + ace.getMessage());
}
}
}
Hope that it helps.
希望它有帮助。