为什么上传到S3的文件具有内容类型application / octet-stream,除非我将文件命名为.html

即使我将内容类型设置为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)); 

但是,如果我将文件命名为最终使用.html

 s3.putObject(new PutObjectRequest(ARTIST_BUCKET_NAME, artistId + ".html", contentsAsStream, md)); 

然后它工作。

我的md对象被忽略了吗? 我如何以编程方式绕过这个,因为随着时间的推移,我需要上传数千个文件,因此不能只进入S3 UI并手动修复contentType。

您必须在代码中执行其他操作。 我刚刚使用1.9.6 S3 SDK尝试了您的代码示例,该文件获取了“text / html”内容类型。

这是确切的(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() } } 

程序打印

text / html的

S3元数据说的相同:

S3属性视图

以下是通过网络发送的通信(由Apache HTTP Commons调试日志记录提供):

 >> PUT /content-type-test HTTP/1.1 >> Host: raniz-playground.s3.amazonaws.com >> Authorization: AWS  >> 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  >> 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 

这也是查看源代码向我们展示的行为 - 如果您设置内容类型,SDK将不会覆盖它。

因为你必须在发送之前在结尾设置内容类型,使用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)); 

上传后,内容类型设置为“ text / html

在此处输入图像描述

这是一个工作的虚拟代码,检查出来,我刚试过,它正在工作;

 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()); } } } 

希望它有所帮助。

看来

上传文件时,如果尚未设置,则AWS S3 Java客户端将尝试确定正确的内容类型。 用户负责确保在上传流时设置合适的内容类型。 如果没有提供内容类型且无法通过文件名确定,则将使用默认内容类型“application / octet-stream”。

为文件提供.html扩展名提供了一种设置正确类型的方法。

根据我一直在看的例子,你展示的代码应该做你想做的事情。 :/

您对S3帐户的默认mime内容有任何覆盖吗? 查看此链接以了解如何检查它: 如何覆盖默认的内容类型 。

无论如何,看起来您的S3客户端无法通过文件内容确定正确的mime类型,因此它依赖于扩展。 当浏览器/ servlet无法确定mimetype时,octet-stream是广泛使用的默认内容mime类型: 是否有默认的mime类型?