сохранение изображения в байтах и загрузка на boto3 возврат содержимого - несоответствие MD5

Я пытаюсь вытащить изображение из s3, квантифицировать его/манипулировать им, а затем сохранить его обратно в 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.

Он отлично работает, если я просто рисую изображение, а затем верну его обратно, не манипулируя им. Я не совсем уверен, что происходит здесь.

Ответ 1

У меня была такая же проблема, и решение заключалось в том, чтобы искать начало сохраненного файла в памяти:

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)

Ответ 2

Возможно, файл необходимо сохранить и перезагрузить, прежде чем отправить его на S3. Поиск указателя файла также должен быть равен 0.

Моя проблема заключалась в отправке файла после прочтения первых нескольких байтов. Открывание файла чисто сделало трюк.

Ответ 3

Я обнаружил, что этот вопрос вызывает ту же ошибку, что и при попытке загрузить файлы, - столкнулись два сценария, одно создание, другая загрузка. Мой ответ заключался в создании с использованием ".filename":

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

Затем сценарий загрузки необходимо игнорировать. файлы. Это обеспечило создание файла.