Rails ignoring custom mime type - ruby-on-rails

My mime_types.rb file has
Mime::Type.register "application/myfoo", :myfoo
And I have a file public/a/test.myfoo
Browsing to localhost:3000/a/test.myfoo returns the file as text/plain.
I am using Chrome 22 and the Accept header is
Accept:text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
I'm using Rails 3.2.8 with the development web server. Am I missing something?

Make sure in your controller the correspondent action looks something like this (I haven't tested it - just to give you a direction):
render :file => #somedir + "/test.myfoo", :content_type => Mime::myfoo
Specifically, the :content_type argument is the most important one.

As of Rails 5, putting this in an initializer works:
Rack::Mime::MIME_TYPES[".manifest"]="text/cache-manifest"
I'm not sure about other versions.
Mime::Type.register "text/cache-manifest", :manifest is only for rails controllers.
source for ActionDispatch::Static: https://github.com/rails/rails/blob/master/actionpack/lib/action_dispatch/middleware/static.rb

Related

Wicked pdf only for certain routes

I have the route /document/:email/:filename, :email => /.*/, :filename => /.*/ that simply takes the filename, searches for it on the storage and returns it. However, after I started using wicked_pdf for other component, the param[:filename] in my controller stopped recognizing the .pdf extension. So before wicked_pdf the route /document/somemail#mail.com/myfile.pdf generated the param param[:filename] == 'myfile.pdf' on my controller, but after I integrated wicked_pdf the param is without the file extension i.e. param[:filename] == 'myfile' how can avoid such behavior?
I don't want wicked_pdf to handle all the pdf files request of my application, only for a specific route/controller
I believe this is because in the Wicked PDF Railtie, it registers the extension like this:
if Mime::Type.lookup_by_extension(:pdf).nil?
Mime::Type.register('application/pdf', :pdf)
end
So before, :filename was just a route parameter, but now that Rails knows there's a matching extension, it seems that it is treating it as a filename that can be followed by an extension, which should be available as params[:format].
You should be able to get the full filename by referring to it as
filename = [params[:filename], params[:format].compact.join('.')
Or unregister the Mime extension like this (maybe in the wicked_pdf initializer):
Mime::Type.unregister(:pdf)
There may also be a way to modify your route globbing to include the extension as part of the filename, but other StackOverflow threads related to that topic seem that it may not be possible to do that without trouble with filenames that also contain periods in them:
How can I get a rails route to keep the extension as part of the id?
ruby on rails - routes.rb - match file extension when multiple periods exist in filename
So I discovered that the pdf extension is removed in the middleware, but I also discovered that the middleware can get some conditions so we can tell when to process the file with wicked_pdf and when not to. See https://github.com/mileszs/wicked_pdf/blob/3e0e2e7bd131365769d230c23ea17b4e52d2702f/lib/wicked_pdf/middleware.rb#L65
Then on my application.rb I just put that condition:
wickedpdfFormat = /wickedpdf_/
config.middleware.use(WickedPdf::Middleware, {}, {:only => [wickedpdfFormat]})
And now I just have to include the wickedpdf_ prefix only for the files I want to be handled by wicked_pdf

How to extend ActionView::Template::Types

With Rails 6.0, the to_spreadsheet gem raises the following error:
Invalid formats: "xlsx", "html"
…/gems/actionview-6.0.0/lib/action_view/lookup_context.rb:288:in `formats='
This gem aside, it seems that ActionViews lookup_context.rb now raises an ArgumentError when formats other then a few basic ones ([:html, :text, :js, :css, :xml, :json]) defined in ActionViews Template types.rb are used.
I tried to extend the basic types like so:
ActionView::Template::Types.symbols.concat([:xlsx, 'xlsx', 'html'])
Although this did indeed add to the ActionView::Template::Types, Rails still raises the ArgumentError described above.
So can these types actually be extended the way I did? Or am I on the completely wrong track to mitigate this error?
Note: MIME-Type for .xlsx is registered by the gem, thats why it worked with Rails versions < 6.
To register a new MIME type, you should add it to config/initializers/mime_types.rb...which should have a commented example of how to add a MIME type (# Mime::Type.register "text/richtext", :rtf).
I would consider not using the to_spreadsheet gem. The last commit was 9 months ago. This may not mean it doesn't work...but I would be skeptical.

Rails 3.x uploading a file via rest-client with S3 :: No such file or dir error

I have a an image file stored on S3. I want to upload that file as form data to a remote site.
Controller line:
response = RestClient.post("#{BASE_URL}/processImage?language=#{LANGUAGE}&exportFormat=txt", :upload => { :file => File.new(asset.avatar.url) })
The asset.avatar.url is a paperclip stored file sitting on S3. It's there. It's publicly accessible.
But I keep getting Errno::ENOENT (No such file or directory) with the url...that works!
I'm probably missing something simple here. Anyone have any ideas?
** EDIT: SOLVED **
I used open-uri, then just used open(). It still downloads to the server, but at least it works. And visually it looks simpler. =)
Here's the fix:
require 'open-uri'
response = RestClient.post("#{BASE_URL}/processImage?language=#{LANGUAGE}&exportFormat=txt", :upload => { :file => open(asset.avatar.url) })
Open-uri is part of ruby, so you don't need to install a gem (ie: rest-client) Just require it in your code.
I thought I'd need a .read in there somewhere, but it seems to work fine without it.
You need to download the file/contents before posting it with RestClient. File.new takes a filepath as argument, not an url.

Returning files from rails

Beginner rails question: How does one return a file from a controller in rails?
I'm familiar with returning/rendering JSON objects. However I've never returned/rendered a file w/ an arbitrary extension.
From reading around SO it sounds like render :nothing => true could help. I'm just looking for some guidance or relevant documentation.
You can use the built-in rails send_file or send_data method.
To stream a file (e.g. for a file proxy endpoint), use send_file:
send_file("#{RAILS_ROOT}/path/to/file/on/server",
:filename => "client-suggested-filename",
:type => "mime/type")
To stream generated data (e.g. for a generated pdf), use send_data:
send_data(your_data,
:filename => "client-suggested-filename",
:type => "mime/type")
The file extension and mime type don't have to match up, but they probably should just to conform to end user expectations. For example, if you are sending with a mime type of application/pdf, you should really set the :filename to something.pdf.
If you're not sure what the mime type is for the file you are sending, you can check this wikipedia page or use the mime-types gem. (Or if you are reading from a database that stores the mime type, use that).

Problems with x_sendfile in Rails

I’m having some problems with John Guenin's x_sendfile (http://john.guen.in/past/2007/4/17/send_files_faster_with_xsendfile/).
When coding the download of a PDF file, I’m using the following code:
def send_the_file(filename)
xsendfile (“#{Rails.root}/doc/” + filename, :type => ‘application/pdf’)
end
but I only get 1 byte downloaded. This usually happens if the filename is not absolute (hence the #{Rails.root} being added. I’ve also checked that the file has the necessary permissions. This is failing both on localhost and my prod site.
Any ideas what I'm doing wrong?
TIA,
Urf
What version of Rails are you using? If you're on 2.1 or later, the X-Sendfile option is built into Rails' send_file method.
send_file 'filename', :x_sendfile => true
Otherwise, are you sure that mod_xsendfile has been installed and configured correctly?
You may want to make sure that your are actually using a web server that supports xsendfile. If you are dev mode you probably aren't and it may fail.
Try to set in apche httpd.conf file
XSendFileAllowAbove on

Resources