Как создать временный url для загрузки файла на Amazon S3 с библиотекой boto?
Я знал, как загрузить файл таким образом - key.generate_url (3600).
Но когда я попытался загрузить: key.generate_url (3600, method = 'PUT'), URL-адрес не работал. Мне сказали: "Подписанная нами подпись запроса не соответствует предоставленной вами подписи. Проверьте свой ключ и метод подписи."
Я не могу найти пример кода на домашней странице boto для использования функции generate_url (method = 'PUT'). Кто-нибудь знает, как использовать его для загрузки? как установить параметры для пути загрузки файла?
Ответы
Ответ 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())