I'm trying to attach CSV files to a Rails3 model using paperclip 4.1.1, but I'm having trouble getting the content-type as reported by S3 to be text/csv
(instead I am getting text/plain
). When I subsequently download the file from S3, the extension is getting changed to match the content-type instead of preserving the original extension (so test.csv is downloaded as test.txt).
From what I can see, when you upload a file, the FileAdapter will cache the content-type on creation with whatever value was determined by the ContentTypeDetector (which calls file -b --mime filename
). Unfortunately, CSV files return text/plain
which makes sense, as how can you really distinguish this? Attempts to set the content-type with attachment.instance_write(:content_type, 'text/csv')
only set the value in the model and do not affect what gets written to S3.
FileAdapter's content_type initialized here: https://github.com/thoughtbot/paperclip/blob/v4.0/lib/paperclip/io_adapters/file_adapter.rb#L14
Call which creates that io_adapter: https://github.com/thoughtbot/paperclip/blob/v4.0/lib/paperclip/attachment.rb#L98
I really have a generic upload here (so I can't hard-code the content type in the S3 headers definition in has_attached_file
), and I don't really want the content-type spoofing protection. Any ideas/suggestions? I would prefer not to downgrade to 3.5 because it would mean just delaying the pain, but if that's the only way, I'll entertain it...
Sure, you could manually go into the S3 console, and set the Content-Type to application/json, but in a CI / CD environments, you want this to happen automatically, maybe by using the AWS CLI. The only way to do this via the command line, is to copy the file.
Well … the AWS CLI for S3 has the flag --content-type but also have a flag called --metadata … but --metadata doesn’t allow you to change the content-type. Instead you can force S3 to think you’re changing the metadata with the flag --metadata-directive REPLACE.
Files that have been uploaded with Paperclip are stored in S3. However, metadata such as the file’s name, location on S3, and last updated timestamp are all stored in the model’s table in the database. Access the file’s url through the url method on the model’s file attribute ( avatar in this example).
Paperclip is an easy file attachment library for ActiveRecord. It treats files like model attributes. This means they aren’t saved to their final locations, nor are they deleted if set to nil, until ActiveRecord::Base#save is called.
If you are using fog
then you can do something like this:
has_attached_file :report,
fog_file: lambda { |attachment|
{
content_type: 'text/csv',
content_disposition: "attachment; filename=#{attachment.original_filename}",
}
}
If you are using Amazon S3 as your storage provider, then something like this should work:
has_attached_file :report
s3_headers: lambda { |attachment|
{
'Content-Type' => 'text/csv',
'Content-Disposition' => "attachment; filename=#{attachment.original_filename}",
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With