Amazon s3 “例外情况”;您指定的内容-MD5与我们收到的内容不匹配;

Amazon s3 “例外情况”;您指定的内容-MD5与我们收到的内容不匹配;,amazon-s3,aws-sdk,Amazon S3,Aws Sdk,我遇到了一个异常,在测试将文件从ec2上传到s3的应用程序时,我从未遇到过。内容是: Exception in thread "Thread-1" com.amazonaws.services.s3.model.AmazonS3Exception: The Content-MD5 you specified did not match what we received. (Service: Amazon S3; Status Code: 400; Error Code: BadDigest; R

我遇到了一个异常,在测试将文件从ec2上传到s3的应用程序时,我从未遇到过。内容是:

Exception in thread "Thread-1" com.amazonaws.services.s3.model.AmazonS3Exception: The Content-MD5 you specified did not match what we received. (Service: Amazon S3; Status Code: 400; Error Code: BadDigest; Request ID: 972CB8E04388AB20), S3 Extended Request ID: T7bmFnQ2RlGWlJD+aGYfTy97XZw88pbQrwNB8YCezSjyq6O2joxHRP/6ko+Q2zZeGewkw4x/90k=
    at com.amazonaws.http.AmazonHttpClient.handleErrorResponse(AmazonHttpClient.java:1383)
    at com.amazonaws.http.AmazonHttpClient.executeOneRequest(AmazonHttpClient.java:902)
    at com.amazonaws.http.AmazonHttpClient.executeHelper(AmazonHttpClient.java:607)
    at com.amazonaws.http.AmazonHttpClient.doExecute(AmazonHttpClient.java:376)
    at com.amazonaws.http.AmazonHttpClient.executeWithTimer(AmazonHttpClient.java:338)
    at com.amazonaws.http.AmazonHttpClient.execute(AmazonHttpClient.java:287)
    at com.amazonaws.services.s3.AmazonS3Client.invoke(AmazonS3Client.java:3676)
    at com.amazonaws.services.s3.AmazonS3Client.putObject(AmazonS3Client.java:1439)
    at com.amazonaws.services.s3.transfer.internal.UploadCallable.uploadInOneChunk(UploadCallable.java:131)
    at com.amazonaws.services.s3.transfer.internal.UploadCallable.call(UploadCallable.java:123)
    at com.amazonaws.services.s3.transfer.internal.UploadMonitor.call(UploadMonitor.java:139)
    at com.amazonaws.services.s3.transfer.internal.UploadMonitor.call(UploadMonitor.java:47)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)

我能做些什么来修复这个错误?我在应用程序中使用了与以前相同的代码

我想我已经解决了我的问题。我最终发现我的一些文件在上传过程中确实发生了变化。因为文件是由另一个线程生成的,所以上传和生成是同时完成的。文件不能立即生成,在生成文件的过程中,可能会同时上传,上传过程中文件实际发生了变化


AmazonS3Client在上传开始时创建了文件的md5,然后将整个文件上传到S3,此时文件与开始上传的文件不同,所以md5实际上发生了变化。我将我的程序修改为单线程程序,问题再也没有出现

我在做这样的事情时也遇到了这个错误:

InputStream productInputStream = convertImageFileToInputStream(file);

InputStream thumbnailInputStream = generateThumbnail(productInputStream);

String uploadedFileUrl = amazonS3Uploader.uploadToS3(BUCKET_PRODUCTS_IMAGES, productFilename, productInputStream);

String uploadedThumbnailUrl = amazonS3Uploader.uploadToS3(BUCKET_PRODUCTS_IMAGES, productThumbnailFilename, thumbnailInputStream);
for(Put obj: thingsToPut)
{
    ObjectMetadata metadata = new ObjectMetadata(); // <<-- New ObjectMetadata every time!
    metadata.setContentType("text/html");
    PutObjectRequest por =
        new PutObjectRequest(bucketName, obj.s3Key, obj.file);
    por = por.withMetadata(metadata);
    PutObjectResult res = s3.putObject(por);
}
generateThumbnail方法使用第三方库操作productInputStream。因为我无法修改第三方库,所以我只是先执行上载:

InputStream productInputStream = convertImageFileToInputStream(file);

// do this first... 
String uploadedFileUrl = amazonS3Uploader.uploadToS3(BUCKET_PRODUCTS_IMAGES, productFilename, productInputStream);

/// and then this...
InputStream thumbnailInputStream = generateThumbnail(productInputStream);

String uploadedThumbnailUrl = amazonS3Uploader.uploadToS3(BUCKET_PRODUCTS_IMAGES, productThumbnailFilename, thumbnailInputStream);
。。。并在我的generateThumbnail方法中添加了这一行:


出现此问题的另一个原因是运行这样的代码(python)

在这种情况下,当文件对象(fd)到达第3行时,它指向文件的末尾,因此我们将得到“Content MD5”错误,为了避免它,我们需要将文件读取器指向文件中的开始位置

with open(filename, 'r') as fd:
     bucket1.put_object(Key=key, Body=fd)
     fd.seek(0)
     bucket2.put_object(Key=key, Body=fd)

这样我们就不会出现前面提到的Boto错误。

FWIW,我设法找到了一种完全不同的触发此问题的方法,这需要不同的解决方案

事实证明,如果您决定显式地将
ObjectMetadata
分配给
PutObjectRequest
,例如指定
cacheControl
设置或contentType,那么AWS SDK会对
ObjectMetadata
实例进行变异,以隐藏它为put请求计算的MD5。这意味着,如果要放置多个对象(您认为所有对象都应该具有相同的元数据),则仍然需要为每个
PutObjectRequest
创建一个新的
ObjectMetadata
实例。如果您不这样做,那么它将重用从上一个put请求计算的MD5,并且您将在尝试放置的第二个对象上得到MD5不匹配错误

因此,明确地说,这样做会在第二次迭代中失败:

ObjectMetadata metadata = new ObjectMetadata();
metadata.setContentType("text/html");
for(Put obj: thingsToPut)
{
    PutObjectRequest por = 
        new PutObjectRequest(bucketName, obj.s3Key, obj.file);
    por = por.withMetadata(metadata);
    PutObjectResult res = s3.putObject(por);
}
您需要这样做:

InputStream productInputStream = convertImageFileToInputStream(file);

InputStream thumbnailInputStream = generateThumbnail(productInputStream);

String uploadedFileUrl = amazonS3Uploader.uploadToS3(BUCKET_PRODUCTS_IMAGES, productFilename, productInputStream);

String uploadedThumbnailUrl = amazonS3Uploader.uploadToS3(BUCKET_PRODUCTS_IMAGES, productThumbnailFilename, thumbnailInputStream);
for(Put obj: thingsToPut)
{
    ObjectMetadata metadata = new ObjectMetadata(); // <<-- New ObjectMetadata every time!
    metadata.setContentType("text/html");
    PutObjectRequest por =
        new PutObjectRequest(bucketName, obj.s3Key, obj.file);
    por = por.withMetadata(metadata);
    PutObjectResult res = s3.putObject(por);
}
for(放置对象:thingsToPut)
{

ObjectMetadata=new ObjectMetadata();//我也遇到了这个问题。我是如何解决这个问题的:

我有一个处理AWS SQS消息的微服务。每条消息将创建多个临时文件,这些文件必须上传到S3

问题是临时文件的名称是固定的,没有添加任何盐

因此,在两条消息之间,可以重写要上载的原始文件


我通过添加随机盐(这可以是UUID,也可以是以毫秒为单位的当前时间,具体取决于您想要什么)文件名,之后文件没有被过度写入,并成功上传到S3。

对于我来说,在执行
上传时,我在参数中使用了
ContentLength
。当它被注释掉时,效果很好

const params = {
  Bucket: "",
  ContentType: "application/json",
  Key: "filename.json",
  // ContentLength: body.length,   <--- what I have commented out
  Body: body
};
await s3.upload(params).promise();
const参数={
桶:“,
ContentType:“应用程序/json”,
键:“filename.json”,

//ContentLength:body.length,如果你在使用
语法和操作文件,这很可能是你的问题。这肯定是我的问题。是的,可能有两个线程处于打开状态:
将open('foo.txt')作为f:with open('bar.txt')作为b:do\u something()