【问题标题】:An exception "The Content-MD5 you specified did not match what we received"异常“您指定的 Content-MD5 与我们收到的不匹配”
【发布时间】:2021-04-15 17:37:28
【问题描述】:

我遇到了一个异常,我在测试将文件从 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)

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

【问题讨论】:

    标签: amazon-s3 aws-sdk


    【解决方案1】:

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

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

    【讨论】:

    • 是的,可能有 2 个线程打开:with open('foo.txt') as f: with open('bar.txt') as b: do_something()
    【解决方案2】:

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

    with open(filename, 'r') as fd:
         self._bucket1.put_object(Key=key, Body=fd)
         self._bucket2.put_object(Key=key, Body=fd)
    

    在这种情况下,文件对象 (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 错误了。

    【讨论】:

    • 如果您使用with 语法和操作文件,这很可能是您的问题。这绝对是我的。
    • 我的问题最终相似,但起初看起来并不相似。我想将全尺寸图像和缩略图图像上传到 S3。我使用 PIL 创建缩略图。问题出在thumbnail = Image.open(image.file) - 当我创建缩略图时,我实际上是在读取原始图像文件。所以我需要像答案建议的那样使用image.file.seek(0)
    【解决方案3】:

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

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

    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 方法中添加了这一行:

    productInputStream.reset();
    

    【讨论】:

      【解决方案4】:

      我也遇到了这个问题。我是如何解决这个问题的:

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

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

      所以在两条消息之间,可以重写要上传的原始文件。

      我通过在文件名中添加随机盐(这可以是 UUID 或当前时间,以毫秒为单位,具体取决于您想要什么)来修复它,之后文件不会被覆盖并成功上传到 S3 .

      【讨论】:

        【解决方案5】:

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

        事实证明,如果您决定将 ObjectMetadata 显式分配给 PutObjectRequest,例如指定 cacheControl 设置或 contentType,则 AWS 开发工具包会改变 ObjectMetadata 实例以存储 MD5它为 put 请求计算。这意味着,如果您要放置多个对象,并且您认为应该为所有这些对象分配相同的元数据,您仍然需要为每个 PutObjectRequest 创建一个新的 ObjectMetadata 实例。如果你不这样做,那么它会重用从前一个 put 请求计算的 MD5,并且你会在你尝试 put 的第二个对象上得到 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);
        }
        

        你需要这样做:

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

        【讨论】:

          【解决方案6】:

          对我来说,我在执行upload 时在参数中使用了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();
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2016-02-08
            • 1970-01-01
            • 1970-01-01
            • 2020-10-25
            • 1970-01-01
            • 1970-01-01
            • 2010-11-16
            • 2017-11-22
            相关资源
            最近更新 更多