Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Set content type in S3 when attaching via Paperclip 4?

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...

like image 595
bheeshmar Avatar asked Apr 17 '14 04:04

bheeshmar


People also ask

How to set content-type to application/json in S3?

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.

How do I change the content-type of S3 metadata?

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.

Where are Paperclip files stored?

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).

What is Paperclip in ActiveRecord?

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.


1 Answers

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}",
    }
  }
like image 125
stereoscott Avatar answered Sep 21 '22 06:09

stereoscott