Python开发:Twilio+Polly场景下S3上传及相关技术问题求助
Hey there! I’ve worked through similar setups with Twilio, Amazon Polly, and S3, so let’s break down your problems step by step:
1. Fixing Boto3’s Content-Type Not Sticking for MP3 Files
The most common issue here is not explicitly setting the ContentType in the upload arguments, or placing it in the wrong spot. Twilio requires audio/mpeg for MP3 files, so make sure you’re passing this in the ExtraArgs parameter when uploading. Here’s a working code snippet:
import boto3 # Initialize S3 client s3_client = boto3.client('s3') local_mp3_path = "generated_polly_voice.mp3" bucket_name = "your-twilio-audio-bucket" s3_object_key = "polly-audio/voice-message.mp3" # Upload with correct content type and public ACL (Twilio needs public access) with open(local_mp3_path, 'rb') as mp3_file: s3_client.upload_fileobj( mp3_file, bucket_name, s3_object_key, ExtraArgs={ "ContentType": "audio/mpeg", "ACL": "public-read" } )
Double-check these potential pitfalls:
- If you were using
upload_fileinstead ofupload_fileobj, theExtraArgsparameter still applies—don’t skip it. - Ensure your S3 bucket doesn’t have a bucket policy or lifecycle rule that overwrites object content types.
- Verify you’re opening the file in binary read mode (
'rb') to avoid corrupting the audio data.
2. Why Boto3 Changes Content-Type to binary/octet-stream
Boto3 tries to auto-detect the content type based on the file’s extension by default. If it can’t recognize the extension (e.g., your file has no extension, or a rare one), it falls back to binary/octet-stream. Other scenarios include:
- You’re uploading raw bytes instead of a file object, so Boto3 has no filename/extension to infer from.
- You forgot to include the
ContentTypeparameter in your upload arguments, leaving S3 to apply its default. - A previous version of the object had
binary/octet-streamand you didn’t overwrite the metadata on re-upload.
3. Uploading to S3 Subdirectories with Tinys3
First, keep in mind: S3 doesn’t have actual subdirectories—they’re just simulated using slashes (/) in the object key. To upload to a "subdirectory", simply include the path in your object key. Here’s how to do it with Tinys3:
from tinys3 import Connection # Initialize Tinys3 connection s3_conn = Connection( aws_access_key_id="YOUR_AWS_KEY", aws_secret_access_key="YOUR_AWS_SECRET", default_bucket="your-bucket-name" ) local_file_path = "polly_output.mp3" # Key includes the subdirectory path: "audio/subfolder/your-file.mp3" s3_object_key = "audio/subfolder/polly-voice.mp3" # Upload with correct content type and public ACL with open(local_file_path, 'rb') as mp3_file: s3_conn.upload( s3_object_key, mp3_file, headers={ "Content-Type": "audio/mpeg", "x-amz-acl": "public-read" } )
After uploading, you’ll see the "subdirectory" structure in the S3 console—this is just S3 grouping objects by the prefix before the slash. You don’t need to create the subdirectory first; uploading an object with a slash in the key will automatically create the visual structure.
内容的提问来源于stack exchange,提问作者Veysel Kocaman

