Uploading a File to a S3 Presigned Url

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



Leave a reply



Submit