2012-04-06 20 views
19

Я знал, как скачать файл таким образом - key.generate_url (3600).Как создать временный url для загрузки файла на Amazon S3 с библиотекой boto?

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

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

+0

Это новый файл? Чтобы создать новый файл, вы должны использовать 'POST', а не' PUT' – vartec

+0

@vartec: Что значит «новый файл»? В моем случае использования иногда мне нужно загрузить новый ключ в определенное ведро, иногда мне нужно перезаписать старый ключ. Поэтому я думаю, что мне нужен пример кода для «PUT» и «POST». –

ответ

40

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

>>> 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 --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, но я этого не пробовал.

+0

Это работает, спасибо большое! –

+2

Аргумент 'headers' в этом ответе не будет работать сейчас, это приведет к ошибке« несоответствия подписи »при загрузке. Если вы хотите указать заголовки * в ответе *, когда вы ПОЛУЧИТЕ файл позже, вам нужно использовать 'response_headers' и использовать такие поля, как' response-content-type' и т. Д. – MLister

+0

Протестировано в облачном хранилище Google, но не удалось. Не могли бы вы взглянуть на этот вопрос? Благодарю. http://stackoverflow.com/questions/38938203/django-heroku-boto-direct-file-upload-to-google-cloud-storage –

8

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

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

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

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

>>> 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 

Тогда я смог использовать завиток, чтобы опубликовать файл:

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

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

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

17

Вот что это похоже на boto3 (проверено с версией 1.2.3).

Во-первых, создать presigned 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' 

поставленному на S3 с presigned 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" 
+0

как вы добавляете свои учетные данные, то есть AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY? – CpILL

+1

@CpILL Вы можете передавать учетные данные через переменные среды. например, $ export AWS_ACCESS_KEY_ID = AKIAIOSFODNN7EXAMPLE http://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-started.html#cli-environment – quiver

+0

отличный ответ, спасибо! –

9

Все остальные ответы считать файл будет загружен с 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()) 
Смежные вопросы