Подтвердить что ты не робот

Как создать временный url для загрузки файла на Amazon S3 с библиотекой boto?

Я знал, как загрузить файл таким образом - key.generate_url (3600).

Но когда я попытался загрузить: key.generate_url (3600, method = 'PUT'), URL-адрес не работал. Мне сказали: "Подписанная нами подпись запроса не соответствует предоставленной вами подписи. Проверьте свой ключ и метод подписи."

Я не могу найти пример кода на домашней странице boto для использования функции generate_url (method = 'PUT'). Кто-нибудь знает, как использовать его для загрузки? как установить параметры для пути загрузки файла?

4b9b3361

Ответ 1

Я нашел время, чтобы поэкспериментировать с этим и здесь, что я нашел.

>>> import boto
>>> c =boto.connect_s3()
>>> fp = open('myfiletoupload.txt')
>>> content_length = len(fp.read())
>>> c.generate_url(300, 'PUT', 'test-1332789015', 'foobar', headers={'Content-Length': str(content_length)}, force_http=True)
'http://test-1332789015.s3.amazonaws.com/foobar?Signature=oUARG45mR95utXsiQYRJNiCI4x4%3D&Expires=1333731456&AWSAccessKeyId=AKIAJOTCCJRP4C3NSMYA&Content-Length=16'

Затем я смог использовать curl для PUT файла для этого url, как это:

$ curl --request PUT --upload-file myfiletoupload.txt "http://test-1332789015.s3.amazonaws.com/foobar?Signature=oUARG45mR95utXsiQYRJNiCI4x4%3D&Expires=1333731456&AWSAccessKeyId=AKIAJOTCCJRP4C3NSMYA&Content-Length=16"

В результате файл загрузился в ведро. Таким образом, кажется, что это возможно. Вы можете посмотреть, можете ли вы вычислить значение content-md5 и включить его в заголовки, но затем вам также нужно выяснить, как получить завиток для отправки этого заголовка. Кроме того, вы должны иметь возможность выполнять эту работу через HTTPS, а не HTTP, но я этого не пробовал.

Ответ 2

Вот как это выглядит в boto3 (протестировано с версией 1.2.3).

Сначала создайте назначенный URL с помощью метода s3.generate_presigned_url:

>>> import boto3
>>> s3 = boto3.client('s3')
>>> s3.generate_presigned_url('put_object', Params={'Bucket':'YourBucket', 'Key':'YourKey'}, ExpiresIn=3600, HttpMethod='PUT')
u'https://s3-ap-northeast-1.amazonaws.com/YourBucket/YourKey?AWSAccessKeyId=AKIAXXXXXXXXXXXXXXXX&Expires=1451061671&Signature=%2FtyAyCd5vrp13p%2FqLdoPkox7yTM%3D'

PUT to S3 с назначенным URL

$ curl \
  --request PUT \
  --upload-file path/to/file \
  "https://s3-ap-northeast-1.amazonaws.com/YourBucket/YourKey?AWSAccessKeyId=AKIAXXXXXXXXXXXXXXXX&Expires=1451061671&Signature=%2FtyAyCd5vrp13p%2FqLdoPkox7yTM%3D"

Ответ 3

Это продолжение ответа на garnaat с 6 апреля '12.

Я создаю подписанную сторону URL-сервера, где у меня есть учетные данные, и я передаю ее клиенту, чтобы клиент мог напрямую загружать контент. Я доверяю клиенту достаточно далеко, чтобы позволить ему загружать файлы произвольного размера, но недостаточно, чтобы придать ему токены безопасности. Я хотел избежать того, чтобы клиент сообщил серверу, насколько его содержимое будет частью запроса. Отсюда мой последующий ответ.

Мне удалось получить подписанный URL-адрес для метода PUT, не указав длину содержимого в заголовках или указав force_http = True.

Использование Boto 2.31.1: как в garnaat answere:

>>> import boto
>>> c =boto.connect_s3()

то вместо этого я использовал:

>>> temp_url = c.generate_url(seconds_available, 'PUT', bucket_name, s3_key)

это создало url в следующем виде:

https://s3_location/bucket_name/s3_key?Signature=Ew407JMktSIcFln%2FZe00VroCmTU%3D&Expires=1405647669&AWSAccessKeyId=kM__pEQo2AEVd_Juz4Qq

Затем я смог использовать curl для публикации файла:

>>> os.system('curl --request PUT --upload-file true_measure/test_files/test_file_w_content.txt "'+temp_url+'"')

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

Надеюсь, что последующий ответ избавит кого-то другого от боли в отладке, которую я прошел.

Ответ 4

Все остальные ответы предполагают, что файл будет загружен с помощью curl, что действительно не удобно в большинстве сценариев python. В дальнейшем предварительно подписанный url генерируется с помощью boto3, и файл загружается с помощью библиотеки requests:

session = boto3.Session(aws_access_key_id="XXX", aws_secret_access_key="XXX")
s3client = session.client('s3')
url = s3client.generate_presigned_url('put_object', Params={'Bucket': 'mybucket', 'Key': 'mykey'})

requests.put(url, data=open("/path/to/file").read())