I have recently switched from carrierwave to shrine in my Rails app and i thought i follow the advice of Alan Richardson, saying when you learn something new, irregardless of how trivial it might seem to you, share it and save someone else that headache.
So in the Yangah application, we upload a number of files to amazon s3 which include images, font files and css files for these fonts. However, i have found that with shrine, out of the box it was not able to correctly set the mime type for the uploaded file on s3.
I actually did try to fix this myself and eventually reach out to the Shrine google group and Janko, the author of the Shrine gem was able to provided a suggestion which worked first time and i am grateful for that.
Here is a link to the actual thread but just incase it gets deleted; this is extract of the message sent by Janko.
determine_mime_typeplugin uses the “file” utility by default for recognizing the MIME type, and it seems to recognize .css files as “text/plain” (and it’s the same for .js files). As noted in the
determine_mime_typeplugin documentation, one analyzer won’t be able to correctly detect correctly all types of files.For text-based file formats (non-binary) it’s probably better to use the “mime_types” analyzer, which uses the mime-types gem to determine the MIME type from the file extension directly (rather than file content). So you could built a custom analyzer that mixes and matches “file” and “mime_types” analyzers; trying the “file” analyzer first, and if the best MIME type that it could come up with was “text/plain” (which is technically correct), then you can call the “mime_types” analyzer to determine which text-based format is it exactly.This way you still get the benefits of the
fileutility preventing someone from uploading a binary file with a .css extension, and use the precision of determining from file extension when needed.
I installed the gem “mime_type” and update the FileUploader class with code snippet below.
plugin :determine_mime_type, analyzer: ->(io, analyzers) do
mime_type = analyzers[:file].call(io)
mime_type = analyzers[:mime_types].call(io) if mime_type == “text/plain”
And that’s it!!! i have the css file now being uploaded correctly with the mime type of “text/css”.