Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to do `PUT` on Amazon S3 using Python Requests

I am trying to upload a file to Amazon S3 with Python Requests (Python is v2.7.9 and requests is v2.7). Following the curl command which works perfectly:

curl --request PUT --upload-file img.png https://mybucket-dev.s3.amazonaws.com/6b89e187-26fa-11e5-a04f-a45e60d45b53?Signature=Ow%3D&Expires=1436595966&AWSAccessKeyId=AQ

But when I do same with requests, it fails. Here's what I have tried:

url = https://mybucket-dev.s3.amazonaws.com/6b89e187-26fa-11e5-a04f-a45e60d45b53?Signature=Ow%3D&Expires=1436595966&AWSAccessKeyId=AQ
requests.put(url, files={'file': base64_encoded_image})
requests.put(url, files={'upload_file': base64_encoded_image})

It fails with 403 and response I am getting is:

<Error><Code>SignatureDoesNotMatch</Code><Message>The request signature we calculated does not match the signature you provided. Check your key and signing method.</Message>

Then I ran curl in verbose mode:

* Hostname was NOT found in DNS cache
*   Trying 54.231.168.134...
* Connected to mybucket-dev.s3.amazonaws.com (54.231.168.134) port 443 (#0)
* TLS 1.2 connection using TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
* Server certificate: *.s3.amazonaws.com
* Server certificate: VeriSign Class 3 Secure Server CA - G3
* Server certificate: VeriSign Class 3 Public Primary Certification Authority - G5
> PUT /6b89e187-26fa-11e5-a04f-a45e60d45b53?Signature=Ow%3D&Expires=1436595966&AWSAccessKeyId=AQ HTTP/1.1
> User-Agent: curl/7.37.1
> Host: mybucket-dev.s3.amazonaws.com
> Accept: */*
> Content-Length: 52369
> Expect: 100-continue
>
< HTTP/1.1 100 Continue
* We are completely uploaded and fine
< HTTP/1.1 200 OK
< x-amz-id-2: 5lLCQ3FVrTBg2vkyk44E+MecQJb2OGiloO0+2pKePtxPgZptKECNlUyYN43sl4LBNe9f8idh/cc=
< x-amz-request-id: 636A24D53DEB5215
< Date: Fri, 10 Jul 2015 12:04:44 GMT
< ETag: "5802130d4320b56a72afe720e2c323a7"
< Content-Length: 0
* Server AmazonS3 is not blacklisted
< Server: AmazonS3
<
* Connection #0 to host mybucket-dev.s3.amazonaws.com left intact

So then I added headers

headers = {'Content-Length': '52369', 'Host': 'mybucket-dev.s3.amazonaws.com', 'Expect': '100-continue', 'Accept': '*/*', 'User-Agent': 'curl/7.37.1'}
requests.put(url, files={'file': base64_encoded_image}, headers=headers)

I tried with different combinations of header, still it throws same error. Then I tried to send query parameters too:

payload={'Expires': '1436595966', 'AWSAccessKeyId': 'AQ', 'Signature': 'Ow%3D'}
requests.put(url, files={'file': base64_encoded_image}, headers=headers, data=payload)

It still fails and same error. I tried URL without query parameters and sending them as data=payload to requests, it fails with same error.

like image 694
avi Avatar asked Jul 10 '15 13:07

avi


People also ask

How do you send request to Amazon S3?

You can send requests to Amazon S3 using the REST API or the AWS SDK (see Sample Code and Libraries ) wrapper libraries that wrap the underlying Amazon S3 REST API, simplifying your programming tasks. Every interaction with Amazon S3 is either authenticated or anonymous.

What is a Put request in S3?

The PUT request operation is used to add an object to a bucket. The response indicates that the object has been successfully stored. S3 never stores partial objects: if you receive a successful response, then you can be confident that the entire object was stored.

How to use Amazon S3 with Python boto3 library?

Amazon S3 with Python Boto3 Library 1 Introduction. ... 2 AWS CLI Installation and Boto3 Configuration. ... 3 S3 Client. ... 4 Create a S3 Bucket. ... 5 Upload a File into the Bucket. ... 6 Creating Folder Structure. ... 7 S3 Application in Data Science. ... 8 Conclusion. ... 9 Complete Project Code. ...

How to access AWS S3 with Python?

In order to access S3 via python, you will need to configure and install AWS CLI and Boto3 Python library. I have already explained that in my previous post. Follow along on how to Install AWS CLI and How to Configure and Install Boto3 Library from that post. Create the boto3 client. Create a response variable and print it.

How do I upload a Python file to a S3 bucket?

You need to specify the path to the file that you want to upload, the bucket name and what do you want to name the file on your bucket. In this case, you have a file called testfile.txt in the same directory as you Python script. I want to upload that to the newly created s3 bucket with the name testfile_s3.txt.

Where can I find the Amazon S3 regions and endpoints?

Dual-stack ‐ s3.dualstack.Region.amazonaws.com For a complete list of Amazon S3 Regions and endpoints, see Amazon S3 endpoints and quotas in the Amazon Web Services General Reference . When making requests by using the REST API, you can use virtual hosted–style or path-style URIs for the Amazon S3 endpoints.


2 Answers

Engineers at requests helped me:

with open('img.png', 'rb') as data:
    requests.put(url, data=data)
like image 95
avi Avatar answered Oct 18 '22 21:10

avi


Acording to this documentation you have pass the files argument to post method also need send the key name for S3

import requests

url = 'https://s3.amazonaws.com/<some-bucket-name>'

data = { 'key': 'test/test.jpeg' }
files = { 'file': open('test.jpeg', 'rb') }

r = requests.post(url, data=data, files=files)
print "status %s" % r.status_code
like image 1
Dima Bruk Avatar answered Oct 18 '22 21:10

Dima Bruk