Как поставить объект на s3 с Content-MD5 - PullRequest
0 голосов
/ 18 октября 2018

Я попытался загрузить файл XML на S3, используя boto3.В соответствии с рекомендациями Amazon, я хотел бы отправить кодированный с помощью Base64 дайджест битов MD5-128 (Content-MD5) данных.

https://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectPUT.html https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/s3.html#S3.Object.put

Мой код:

with open(file, 'rb') as tempfile:
   body = tempfile.read()
tempfile.close()

hash_object = hashlib.md5(body)
base64_md5 = base64.encodebytes(hash_object.digest())

response = s3.Object(self.bucket, self.key + file).put(
            Body=body.decode(self.encoding),
            ACL='private',
            Metadata=metadata,
            ContentType=self.content_type,
            ContentEncoding=self.encoding,
            ContentMD5=str(base64_md5)
        )

Когда я пытаюсь это сделать, str (base64_md5) создает строку типа 'b'ZpL06Osuws3qFQJ8ktdBOw == \ n' '

В этом случае я получаю это сообщение об ошибке:

An error occurred (InvalidDigest) when calling the PutObject operation: The Content-MD5 you specified was invalid.

Для целей тестирования я скопировал только Значение без 'b' спереди: 'ZpL06Osuws3qFQJ8ktdBOw == \ n'

Затем я получаю это сообщение об ошибке:

botocore.exceptions.HTTPClientError: An HTTP Client raised and unhandled exception: Invalid header value b'hvUe19qHj7rMbwOWVPEv6Q==\n'

Может кто-нибудь помочь мне, как сохранить Загрузить файл на S3?

Спасибо,

Оливер

1 Ответ

0 голосов
/ 13 декабря 2018

(Python 3.7)

У меня ушло несколько часов, чтобы понять это, потому что единственная ошибка, которую вы получаете, - «Указанный вами Content-MD5 недействителен».Супер полезно для отладки ... Во всяком случае, вот код, который я использовал, чтобы получить файл для правильной загрузки перед рефакторингом.

json_results = json_converter.convert_to_json(result)
json_results_utf8 = json_results.encode('utf-8')
content_md5 = md5.get_content_md5(json_results_utf8)
content_md5_string = content_md5.decode('utf-8')
metadata = {
    "md5chksum": content_md5_string
}
s3 = boto3.resource('s3', config=Config(signature_version='s3v4'))
obj = s3.Object(bucket, 'filename.json')
obj.put(
    Body=json_results_utf8,
    ContentMD5=content_md5_string,
    ServerSideEncryption='aws:kms',
    Metadata=metadata,
    SSEKMSKeyId=key_id)

и хэширование

def get_content_md5(data):
    digest = hashlib.md5(data).digest()
    return base64.b64encode(digest)

Сложная частья выяснил, какая кодировка вам нужна на каждом этапе процесса, и не очень хорошо знал, как в то время хранятся строки в python.

get_content_md5 принимает только объект, похожий на байты utf-8и возвращает то же самое.Но чтобы передать хэш md5 в aws, это должна быть строка.Вы должны расшифровать его перед тем, как передать его ContentMD5.

Pro-tip - Body, с другой стороны, необходимо предоставить байты или объект для поиска.Убедитесь, что если вы передаете объект поиска, который вы seek(0), в начало файла, прежде чем передать его в AWS, иначе MD5 не будет соответствовать.По этой причине использование байтов менее подвержено ошибкам, imo.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...