Download S3 Objects With Custom Filenames: CLI, Python, and Content-Disposition

1. S3 Download Using AWS CLI (No Custom Headers)

To download a file and save it with a different name:

aws s3 cp s3://<bucket-name>/<file-key> <local-custom-filename>

Example:

aws s3 cp s3://my-bucket/reports/data.csv ./monthly_report.csv
  • Downloads data.csv from S3 and saves it locally as monthly_report.csv.
  • No headers like Content-Disposition are involved.

2. Python: Pre-signed URL Without Content-Disposition

Generate a pre-signed URL and download the file. Filename remains client-controlled.

import boto3
import requests
def download_presigned(bucket, key, save_as, expires=3600):
s3 = boto3.client('s3')
url = s3.generate_presigned_url('get_object', Params={'Bucket': bucket, 'Key': key}, ExpiresIn=expires)
print(f"Generated URL: {url}")
response = requests.get(url, stream=True)
if response.status_code == 200:
with open(save_as, 'wb') as f:
for chunk in response.iter_content(8192):
f.write(chunk)
print(f"Saved as {save_as}")
else:
print(f"Failed: {response.status_code}")
download_presigned("my-bucket", "reports/data.csv", "monthly_report.csv")
  • Key: The filename saved (monthly_report.csv) is determined locally.
  • The S3 response header doesn’t enforce naming.

3. Python: Pre-signed URL With Content-Disposition

To enforce a download filename from S3, modify the pre-signed URL to include ResponseContentDisposition.

import boto3
import requests
def download_with_header(bucket, key, custom_filename, expires=3600):
s3 = boto3.client('s3')
url = s3.generate_presigned_url(
'get_object',
Params={
'Bucket': bucket,
'Key': key,
'ResponseContentDisposition': f'attachment; filename="{custom_filename}"'
},
ExpiresIn=expires
)
print(f"Generated URL with Content-Disposition: {url}")
response = requests.get(url, stream=True)
if response.status_code == 200:
with open(custom_filename, 'wb') as f:
for chunk in response.iter_content(8192):
f.write(chunk)
print(f"Downloaded as {custom_filename}")
else:
print(f"Failed: {response.status_code}")
download_with_header("my-bucket", "reports/data.csv", "monthly_report.csv")

4. What is Content-Disposition?

Content-Disposition is an HTTP header that controls how browsers handle file downloads.

  • Format:
Content-Disposition: attachment; filename="custom_name.txt"
  • attachment: Instructs the browser to download the file instead of displaying it.
  • filename: Specifies the name the file will be saved as.

Without Content-Disposition, the default filename comes from the S3 key (e.g., data.csv).

With Content-Disposition, you control the filename on the client side, useful for file-sharing or dynamic naming.

Why Use Content-Disposition?

  1. Consistent naming for downloads (e.g., report_2024.pdf).
  2. Avoid relying on client-side naming.
  3. Helps enforce naming policies for external access.

Final Notes

  • CLI: Simple for internal downloads.
  • Without Content-Disposition: Local control, no S3 enforcement.
  • With Content-Disposition: Enforce client-side naming directly from S3.

Choose the right tool for your needs. When in doubt, control naming with Content-Disposition.

Learn more Download S3 Objects With Custom Filenames: CLI, Python, and Content-Disposition

Leave a Reply