求助:Boto3调用put_object设置S3加密致文件变为0字节
Hey Ameer, sorry to hear you're stuck with this frustrating problem—let's break this down and get you sorted, starting with recovering your files.
Why Your Objects Turned to 0 Bytes
The root issue is how the put_object API works in Boto3: when you call it with only Bucket, Key, and ServerSideEncryption (without specifying a Body parameter), you're replacing the existing object with an empty one. Unlike the S3 console's manual encryption (which modifies the object's encryption settings without touching the actual content), this API call creates a brand new zero-byte object that overwrites your original file entirely.
How to Recover Your Files
Your recovery options depend on the S3 features you had enabled before the overwrite:
- If Versioning was turned on for the bucket: Head to the S3 console, navigate to your object, click the "Versions" tab, and you'll see all previous versions of the file. Restore the non-zero-byte version to get your data back.
- If you use AWS Backup or Cross-Region Replication (CRR): Check your backup vault or replicated bucket—your original files might be stored there.
- If no versioning/backups exist: Reach out to AWS Support right away. They may be able to help recover overwritten objects, though success depends on how much time has passed since the overwrite.
Correct Way to Enable Server-Side Encryption on Existing Objects
Instead of using put_object, use the copy_object API to copy the object onto itself while applying encryption. This preserves the original content and adds the encryption setting:
import boto3 client = boto3.client('s3') # Enable AES256 encryption on an existing object without losing content client.copy_object( Bucket=bucket_name, Key=object_key, CopySource={'Bucket': bucket_name, 'Key': object_key}, ServerSideEncryption='AES256', # Add this to preserve original object metadata MetadataDirective='COPY' )
For bulk operations (encrypting all objects in a bucket), loop through objects using list_objects_v2 and apply the copy_object call to each one.
Bonus: Set Bucket-Level Default Encryption
To avoid manual encryption tasks in the future, set a default encryption rule for your bucket. All new objects uploaded will automatically use AES256 encryption:
client.put_bucket_encryption( Bucket=bucket_name, ServerSideEncryptionConfiguration={ 'Rules': [ { 'ApplyServerSideEncryptionByDefault': { 'SSEAlgorithm': 'AES256' } } ] } )
Pro tip: Always test scripts on a small set of test objects first before running them on production data!
内容的提问来源于stack exchange,提问作者Mohd Ameer Yuslan Razmi

