How do I upload a file into an Amazon S3 signed url with python?
Once you have the pre-signed url, you don't need boto3 at all. Instead you can use regular python functions for uploading files to S3. For example using python's requests. Also you should be using generate_presigned_post
def create_presigned_post(bucket_name, object_name,
fields=None, conditions=None, expiration=3600):
"""Generate a presigned URL S3 POST request to upload a file
:param bucket_name: string
:param object_name: string
:param fields: Dictionary of prefilled form fields
:param conditions: List of conditions to include in the policy
:param expiration: Time in seconds for the presigned URL to remain valid
:return: Dictionary with the following keys:
url: URL to post to
fields: Dictionary of form fields and values to submit with the POST
:return: None if error.
"""
# Generate a presigned S3 POST URL
s3_client = boto3.client('s3')
try:
response = s3_client.generate_presigned_post(bucket_name,
object_name,
Fields=fields,
Conditions=conditions,
ExpiresIn=expiration)
except ClientError as e:
logging.error(e)
return None
# The response contains the presigned URL and required fields
return response
result = create_presigned_post("bucket123", "test.txt")
import requests # To install: pip install requests
# Generate a presigned S3 POST URL
object_name = 'test.txt'
result = create_presigned_post("marcin3", object_name)
# Demonstrate how another Python program can use the presigned URL to upload a file
with open(object_name, 'rb') as f:
files = {'file': (object_name, f)}
http_response = requests.post(result['url'], data=result['fields'], files=files)
# If successful, returns HTTP status code 204
logging.info(f'File upload HTTP status code: {http_response.status_code}')
Can't upload a file to S3 with pre-signed URL no matter what I do. AWS command line works. CURL and anything else = 403
SOLUTION: Turns out the Boto3 I was using wasn't up to date and I was using it wrong. After fixing those, the code that worked for me was:
# THE CREDENTIALS ARE PART OF MY TESTING CODE. NO WORRIES THEY'RE IN AN ENV VARIABLE NOW
def get_upload_pre_signed_url(bucket_name, key, expiration=3600):
s3 = boto3.client('s3',
aws_access_key_id="<my access_key_id",
aws_secret_access_key="<my_secreet_access_key>",
config=Config(region_name='us-east-2', s3.{"use_accelerate_endpoint": True}))
try:
url = s3.generate_presigned_url('put_object', Params={'Bucket': bucket_name, 'Key': key},
ExpiresIn=expiration,
HttpMethod='PUT')
except ClientError as e:
return None
return url
Related Topics
Getting a Rogue Iteration from My .Each Loop
Import CSV in Batches of Lines in Rails
Open Xml File with Nokogiri Update Node and Save
How to Implement Editing/Formating Text Area in Rails
Kaminari Undefined Method 'Total_Pages'
Ruby Getting Deeply Nested JSON API Data
Which Global Variable Is for Last Expression
Ruby#Index Method VS Binary Search
Why Non-Explicit Splat Param Plus Default Param Is Wrong Syntax for Method Definition in Ruby 1.9
Hardcoded "Require 'Debug'" Can't Find the Sourcefile
How to Use String Methods on Utf-8 Characters
Testing HTML5 File Upload with Capybara/Selenium Webdriver - Ruby
How to Access HTML Elements That Are Rendered in JavaScript Using Xpath
How to Run Rails App in a Completely Isolated Instances of Chrome
How to Link to a Page with Page.Url Without the HTML Extension in Jekyll