Do you care about ContentDisposition header in ActiveStorage?
Recently, I ran into an interesting problem: Some of the PDF files on my work project’s opened directly in the browser but some downloaded.
Do you care about Content Disposition header in Active Storage?
Recently, I ran into an interesting problem: Some of the PDF files on my work project’s website opened directly in the browser (inline), while others were downloaded.
The project itself is pretty old, it had started with Rails 5 and was upgraded to 6 and then 7 version over last 8 years. Somewhere along the way, some configuration got out of sync.
Check Rails configuration
Rails has a setting for which file types can be shown inline:
config.active_storage.content_types_allowed_inline = [
“image/png”,
“image/jpeg”,
“image/gif”,
“image/webp”,
“application/pdf”
]
After upgrading to Rails 7, I made sure application/pdf was added to this list.
What about S3?
In our case, files are stored in public AWS S3 bucket. We don’t proxy files through Rails with rails_blob_path or redirects. Instead, customers get a direct link to the file on S3 or Cloudfront CDN depending on our needs.
At first, my idea was simple - use Rails helper like this:
rails_blob_path(attachment, disposition: “inline”)
But this only works if the file doesn’t already have a Content-Disposition: attachment header set in S3 metadata (Interesting fact that this header is set as System). And of course, a lot of old files had it.
So even with the Rails config fixed, the browser was still forcing downloads.
Debug
Before changing anything, it’s useful to check what headers a file has:
s3 = Aws::S3::Client.new(
region: “your-region”
access_key_id: ENV[“AWS_ACCESS_KEY_ID”],
secret_access_key: ENV[“AWS_SECRET_ACCESS_KEY”]
)
bucket = "your_bucket_name"
key = "your_file_key"
response = s3.head_object(bucket: bucket, key: key)
response.content_disposition
If you see attachment, that’s the reason your PDF is being downloaded.
Fixing old files
Unfortunately, you can’t just update metadata in place on S3. The trick is to copy the file onto itself with updated metadata:
resp = s3.head_object(bucket: bucket, key: key)
s3.copy_object(
bucket: bucket,
key: key,
copy_source: "#{bucket}/#{key}",
metadata_directive: 'REPLACE',
content_type: resp.content_type,
content_disposition: nil, # remove "attachment"
metadata: resp.metadata # keep custom metadata
)
response = s3.head_object(bucket: bucket, key: key)
response.content_disposition
Now the file doesn’t force download anymore. Browsers will open it inline.
Once content_types_allowed_inline is configured correctly, and old files are fixed, all new uploads will work fine too.
That’s it. Now, your users will see PDFs open directly in their browser instead of automatically downloading.
메타데이터
- post_id
- 031f89d75cd2
- slug
- do-you-care-about-contentdisposition-header-in-activestorage-031f89d75cd2
- url
- https://medium.com/@melnic404/do-you-care-about-contentdisposition-header-in-activestorage-031f89d75cd2
- canonical_url
- https://medium.com/@melnic404/do-you-care-about-contentdisposition-header-in-activestorage-031f89d75cd2
- author_url
- https://medium.com/@melnic404
- status
- ok
- fetched_at
- 2026-07-17 07:03:26