Download a file using a document link labeled Carrierwave

I am trying to make a simple link that, when clicked, initiates the download of a document associated with a specific resource. I have a resource model, and in this model there is a column called "document". I can successfully view the document in a row by clicking a link, but I would prefer to download it. I read about content types and the send_file, but I was not able to completely put this together to work.

Here is the code that I think I need to use for the link:
<%= link_to 'Download File', :action => "download_file" %>

This causes an error:
ActiveRecord :: RecordNotFound in ResourcesController # show Could not find resource with id = download_file

When I change the link to this, it opens the file in the browser:
<%= link_to 'Open file', resource.document_url, :target => "_blank" %>

In my ResourceController, I have this method:

  def download_file @resource = Resource.find(params[:id]) send_file(@resource.file.path, :filename => @resource.file.name, :type => @resource.file.content_type, :disposition => 'attachment', :url_based_filename => true) end 

I have a route set in routes.rb as follows:

  resources :resources do get 'resources', :on => :collection end 

Therefore, based on this error, it seems to me that my download_file method in the ResourceController cannot determine the identifier of the resource record with which the document is associated.

I run: Rails 3.2.11 Carrierwave 0.8.0 Ruby 1.9.3-p194

I would like to get some idea about this. I searched for several articles and could not find a simple tutorial. Thanks.

+8
ruby-on-rails-3 download carrierwave
source share
1 answer

I was able to figure it out. I will try to explain how I fixed this problem.

The download_file method was correctly located in the ResourceController, but I did not use the correct variable names. Here is the correct method definition for my purposes:

  def download_file @resource = Resource.find(params[:id]) send_file(@resource.document.path, :type => 'application/pdf', :disposition => 'attachment', :url_based_filename => true) end 

In my case, I have an entry returned in the @resource variable that has a document associated with it (again, I use Carrierwave). Thus, the first argument required for send_file is the path (see the API for send_file ). This path information is provided at @ resource.document.path.

send_file accepts a number of other arguments that seem optional because I only need three of them. See the API documentation for other arguments.

One of those who threw an error for me was type :. I passed the variable "@ resource.file.content_type" to it, but it was clearly looking for a literal. When I passed this application / pdf, it worked. Without explicitly specifying this file, the downloaded file does not add the file extension. In any case, for my application this document can be a lot of different mime types from pdf to word to mp4. Therefore, I am not sure how to specify a few.

A really important argument for my purposes (to load instead of displaying in the browser) is: the location, which should be set to "attachment" and not to "inline".

Another argument: url_based_filename is apparently used to determine the file name from the url. Since I am not supplying a file name, this may be the only way to provide this to a downloadable file, but I'm not sure about that.

I also needed to change the link_to tag: <%= link_to 'Download File', :action => 'download_file', :id => resource.id %>

Note that providing the: id symbol with the identifier of the current resource provided the specific information needed to identify the resource in question.

I hope this helps someone else. This should be very obvious to everyone else, because I did not find the basic file upload guides. I am still learning a lot.

UPDATE: I needed to play around with this in order to achieve the desired behavior. Here is a new method that works:

  def download_file @resource = Resource.find(params[:id]) send_file(@resource.document.path, :disposition => 'attachment', :url_based_filename => false) end 

With these changes, I no longer need to set the type :. The setting ": url_based_filename => true" continued to name the file after the record identifier in the URL. Setting this value to false seems inconsistent, based on my reading of the function of this argument, however this led to the desired results of naming the file after the actual file name.

I also used mime-types gem and added the following to my video_uploader.rb file:

 require 'carrierwave/processing/mime_types' class VideoUploader < CarrierWave::Uploader::Base include CarrierWave::MimeTypes process :set_content_type 

This pearl apparently sets the mime type, presumably from the file extension in the file name. To do this, I did not need to install: enter explicitly the send_file arguments inside my download_file method.

+13
source share

All Articles