将图像保存为字节并上传到 boto3 返回内容-MD5 不匹配

saving an image to bytes and uploading to boto3 returning content-MD5 mismatch

我正在尝试从 s3 中提取图像,对其进行量化 it/manipulate,然后将其存储回 s3,而不将任何内容保存到磁盘(完全在内存中)。我能够做到一次,但在返回代码并再次尝试时它没有用。代码如下:

import boto3
import io
from PIL import Image

client = boto3.client('s3',aws_access_key_id='',
        aws_secret_access_key='')
cur_image = client.get_object(Bucket='mybucket',Key='2016-03-19 19.15.40.jpg')['Body'].read()

loaded_image = Image.open(io.BytesIO(cur_image))
quantized_image = loaded_image.quantize(colors=50)
saved_quantized_image = io.BytesIO()
quantized_image.save(saved_quantized_image,'PNG')
client.put_object(ACL='public-read',Body=saved_quantized_image,Key='testimage.png',Bucket='mybucket')

我收到的错误是:

botocore.exceptions.ClientError: An error occurred (BadDigest) when calling the PutObject operation: The Content-MD5 you specified did not match what we received.

如果我只是拉出一个图像,然后在不对其进行操作的情况下将其放回原位,则效果很好。我不太确定这里发生了什么。

在将文件发送到 S3 之前,可能需要保存并重新加载该文件。文件指针查找也需要在 0.

我的问题是在读出文件的前几个字节后发送文件。干净利落地打开文件就可以了。

我遇到了同样的问题,解决方案是查找保存的 in-memory 文件的开头:

out_img = BytesIO()
image.save(out_img, img_type)
out_img.seek(0)  # Without this line it fails
self.bucket.put_object(Bucket=self.bucket_name,
                       Key=key,
                       Body=out_img)

我发现这个问题在尝试上传文件时遇到同样的错误 -- 两个脚本冲突,一个创建,另一个上传。我的答案是使用“.filename”创建然后:

os.rename(filename.replace(".filename","filename"))

然后上传脚本需要忽略。文件。这确保文件已完成创建。

对于面临类似错误的任何其他人来说,这通常发生在文件内容在文件上传过程中被修改时,可能是由于文件被另一个人修改 process/thread。

一个典型的例子是同时修改同一个文件的脚本,由于 MD5 内容的变化而抛出错误的摘要。在下面的例子中,数据文件正在上传到s3,在上传的过程中,如果另一个进程覆盖它,你会得到这个异常

random_uuid=$(uuidgen)
cat data
aws s3api put-object --acl bucket-owner-full-control --bucket $s3_bucket --key $random_uuid --body data