2012-04-06 11 views
19

Wiedziałem, jak pobrać plik w ten sposób - key.generate_url (3600).Jak wygenerować tymczasowy URL do przesłania pliku do Amazon S3 z biblioteką Boto?

Ale kiedy próbowałem przesłać: key.generate_url (3600, method = 'PUT'), adres URL nie zadziałał. Powiedziano mi: "Obliczona przez nas prośba o podpis nie zgadza się z podanym przez Ciebie podpisem. Sprawdź klucz i metodę podpisywania."

nie mogę znaleźć przykładowy kod w głównej boto do sposobu korzystania z generate_url function (method = „PUT”). Czy ktoś tutaj wie, jak go użyć do przesłania? jak ustawić parametry ścieżki przesyłania pliku?

+0

Czy to nowy plik? Aby utworzyć nowy plik, należy użyć 'POST', a nie' PUT' – vartec

+0

@vartec: Co to znaczy "nowy plik"? W moim przypadku użycia czasami muszę załadować nowy klucz do określonego zasobnika, czasami muszę nadpisać stary klucz. Myślę więc, że potrzebuję przykładu kodu "PUT" i "POST". –

Odpowiedz

40

Znalazłem trochę czasu na eksperymentowanie z tym i oto co znalazłem.

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

byłem wtedy w stanie wykorzystać pozwijane umieścić plik do tego adresu URL tak:

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

Spowodowało plik jest dodany do wiadra. Wydaje się więc, że jest to możliwe. Możesz sprawdzić, czy możesz obliczyć wartość content-md5 i uwzględnić ją w nagłówkach, ale musisz również dowiedzieć się, jak uzyskać curl, aby wysłać ten nagłówek. Poza tym powinieneś być w stanie zrobić to za pomocą HTTPS zamiast HTTP, ale tego nie próbowałem.

+0

Działa, dziękuję bardzo! –

+2

"Argumenty nagłówkowe w tej odpowiedzi nie będą teraz działały, spowoduje to błąd" błędnego podpisu "podczas przesyłania. Jeśli chcesz określić nagłówki * w odpowiedzi *, gdy odbierzesz plik później, musisz użyć 'response_headers' i użyć pól takich jak' typ-odpowiedzi-odpowiedzi' itp. – MLister

+0

Testowany w Google Cloud Storage, ale się nie powiodło. Czy mógłbyś rzucić okiem na to pytanie? Dzięki. http://stackoverflow.com/questions/38938203/django-heroku-boto-direct-file-upload-to-google-cloud-storage –

8

Jest to kontynuacja odpowiedzi na garnaat od kwietnia 6 '12.

Generuję stronę ze podpisanym adresem URL serwera, na którym mam poświadczenia i przekazuję ją klientowi, tak aby klient mógł bezpośrednio przesłać zawartość. Ufam klientowi wystarczająco daleko, aby mógł przesyłać pliki o dowolnych rozmiarach, ale nie na tyle, aby nadać mu tokeny zabezpieczające. Chciałem uniknąć sytuacji, w której klient poinformuje serwer o tym, jak duża jego zawartość będzie częścią żądania. Stąd moja odpowiedź.

Udało mi się uzyskać podpisany adres URL działającej metody PUT bez określania długości treści w nagłówkach lub określania force_http = True.

Korzystanie boto 2.31.1: jak w garnaat za answere:

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

wtedy zamiast użyłem:

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

ten produkowany URL w następującej postaci:

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

Byłem wtedy w stanie użyć curl, aby opublikować plik:

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

Miałem bardzo trudny czas, zastanawiając się nad tym, ponieważ zazwyczaj używam python requests do pisania testów i debugowania; jednak otrzymuję niepowodzenie uwierzytelniania, gdy próbuję go użyć, aby umieścić plik w jednym z tych wygenerowanych boto podpisanych adresów URL za pomocą żądań. Nie w pełni to debugowałem, ale podejrzewam, że tak jest, ponieważ żądania dodają kilka dodatkowych nagłówków w porównaniu do tego, co wytwarza curl.

Mam nadzieję, że ta odpowiedź uzupełniająca sprawi, że ktoś inny przejdzie przez ten debugujący ból.

17

Oto, jak to wygląda w boto3 (testowane z wersją 1.2.3).

Najpierw utwórz presigned URL z s3.generate_presigned_url metody:

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

oddany do S3 z 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

jak dodać swoje poświadczenia, np. AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY? – CpILL

+1

@ CpILL Możesz przekazywać referencje za pomocą zmiennych środowiskowych. np. $ export AWS_ACCESS_KEY_ID = AKIAIOSFODNN7EXAMPLE http://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-started.html#cli-environment – quiver

+0

Świetna odpowiedź, dzięki! –

9

Wszystkie inne odpowiedzi zakładają plik zostanie przesłany z curl, która jest naprawdę nie jest to wygodne w przypadku większości skryptów Pythona. W dalszej części pre-podpisane url jest generowany z boto3 a plik zostanie przesłany z requests Biblioteka:

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()) 
Powiązane problemy