patternpythonawsModeratepending
AWS S3 pre-signed URLs for secure file uploads
Viewed 0 times
pre-signed urls3 uploaddirect uploadpresignedclient upload
Problem
Need to allow users to upload files directly to S3 without exposing AWS credentials or routing through your server.
Solution
Pre-signed URLs enable direct client-to-S3 uploads:
Security:
# Server: Generate pre-signed URL
import boto3
from uuid import uuid4
def create_upload_url(content_type, max_size_mb=10):
s3 = boto3.client('s3')
key = f'uploads/{uuid4()}/{content_type.split("/")[-1]}'
url = s3.generate_presigned_url(
'put_object',
Params={
'Bucket': 'my-bucket',
'Key': key,
'ContentType': content_type,
},
ExpiresIn=300, # URL valid for 5 minutes
)
return {'upload_url': url, 'key': key}
# API endpoint
@app.post('/api/upload-url')
def get_upload_url(content_type: str):
return create_upload_url(content_type)// Client: Upload directly to S3
async function uploadFile(file) {
// 1. Get pre-signed URL from your API
const { upload_url, key } = await fetch('/api/upload-url', {
method: 'POST',
body: JSON.stringify({ content_type: file.type }),
}).then(r => r.json());
// 2. Upload directly to S3
await fetch(upload_url, {
method: 'PUT',
headers: { 'Content-Type': file.type },
body: file,
});
return key; // Save this to your database
}Security:
- Set short expiry (5-15 minutes)
- Validate content type on server
- Use S3 bucket policies to restrict file types/sizes
- Never expose AWS credentials to the client
- Set CORS on the S3 bucket for browser uploads
Why
Pre-signed URLs eliminate the need to proxy large files through your server, reducing bandwidth costs, latency, and server load.
Gotchas
- CORS must be configured on the S3 bucket for browser uploads
- Content-Type in the PUT must match what was signed
- Pre-signed URLs are single-use - generate a new one for each upload
Context
Web applications needing file upload functionality
Revisions (0)
No revisions yet.