How to download file with id params? - ruby-on-rails

Hello I try to download a jpeg image on rails by verifying that the Post exists and by recovering its id in parameter.
I try something but i got a error... I show you:
def download
send_file '/public/uploads/posts/#image/image.jpg', :type => 'image/jpeg', :disposition => 'attachment', :x_sendfile => true
end
private
def set_image
#image = Post.find(params[:id])
end
In my controller I have to in my routes get download.
And my link_to is:
<%= link_to "Download", download_posts_path %>
But rails say to me "Couldn't find Post without an ID".
I don't understand why... He dont't have the id but I dont't know why ?

Assuming you use set_image in a before_action filter.
First you should pass the post instance or id to your route helper :
If your route takes a param e.g. /posts/:id/download :
<%= link_to "Download", download_posts_path(#post) %>
<%= link_to "Download", download_posts_path(#post.id) %>
If not you can pass it with a query parameter e.g. posts/download/?id=1
<%= link_to "Download", download_posts_path(id: #post.id) %>
Both solution will provide you a params[:id] in your controller. Otherwise params[:id] will be nil and find raises an error.
Then there's something wrong in the download action as #DileepNandanam pointed out. You're not using your Post instance (#image) at all, you're just passing send_file a string containing "#image", not the variable but just a string. You may want to use interpolation to build a valid path to your image. For example if your #image has a :name which could be "image.jpg" you would do it like this:
send_file "/public/uploads/posts/#{#image.name}"
Or you could name your images with the post id like 13.jpg then you'll do :
send_file "/public/uploads/posts/#{#image.id}.jpg"
Or even create separate forlders with post's ids :
send_file "/public/uploads/posts/#{#image.id}/image.jpg"

send_file "/public/uploads/posts/#{#image.image_file_name}/image.jpg", :type => 'image/jpeg', :disposition => 'attachment', :x_sendfile => true
The method image_file_name may varies depends on the attachment you have specified on model
A better way is to use the url for attachment like
send_file #image.image.url(:original)

Related

Ruby on Rails send_file doesn't work until i refresh the page?

I am working on a Rails server which I can download my locally stored movies and anime etc from. This is kind of working but when I click the download link I have to refresh the page in order for the download to actually start.
This is the controller that handles the download:
class DownloadController < ApplicationController
def index
#title = params[:title]
#name = params[:name]
#path = '/media/sf_Anime,_VN,_LN/Watching, not watched yet/'+#title+'/'+#name
send_file( #path )
end
end
and this is the link that links to that controller:
<% #episodes.each do |x| %>
<p> <%= x %><%= link_to " Download",
{controller: 'download', action: 'index', title: #title, name: x } %> </p>
<% end %>
edit:
I did some testing today and noticed that the download links work instantly if i try to send a smaller file (text or image). I also noticed that the download links actually works for the movies aswell but it takes 20-30 seconds for the download to start.
Do you have any idea of what would cause this delay?
Are you using turbolinks? Turbolinks apparently doesn't play nicely with send_file (https://github.com/rails/turbolinks/issues/182). Try adding "data: { no-turbolink: true }" (or "'data-no-turbolink'=>true") in the link_to helper, e.g.:
<%= link_to "Downloadable File", downloadable_file, data: { no-turbolink: true } %>
See also: Rails 4, asset pipeline causes user downloadable files to be downloaded twice, rails won't send_data as file, Ruby on Rails send_file, code in controller action running twice
Edited to reflect comment below. I would simple add a concern for handling downloads and then use
include Concerns::Downloads
to handle your download request. the routes.rb would look like this.
resources :movies do
member do
post 'download'
end
and in the view
<%= link_to 'Download', {:controller => 'movies', :action => 'download'}, {:method => :post } %></a>
Move the file to public folder
add only file name into link_to
<%= link_to "Downloadable File", "/"+filename, %>
Try setting the disposition to attachment in send_file:
class DownloadController < ApplicationController
def index
...
send_file( #path, :disposition => 'attachment' )
end
end
The issue may be that your browser is trying to open the file itself - :disposition => 'attachment' prompts the browser to download the file, even if it thinks the file is something that it can open.

How to create a download button (link) for a local image (png)

In my Ruby on Rails 4 application I want to provide the user with a download for a png image.
Firstly, where would this png need to be placed:
/public
/assets/images
Secondly, how would I do that?
I've tried what the 2nd answer here says, and I am getting this error:
No route matches [GET] "/public/diagram.png"
The implementation of the above answer:
At my view:
<%= link_to "DOWNLOAD", "/public/diagram.png" %>
The controller:
class ControllerNamesController < ApplicationController
// other actions defined: index, show, create, new, edit, update, destroy
def download_png
send_file(
"#{Rails.root}/public/diagram.png",
filename: "diagram.png",
type: "application/png"
)
end
Τhe routes file (has all the controllers defined like this):
resources :ControllerName
get "ControllerName/download_png", as: :download
Try using this
view
<%= link_to "Download" ,:action => :download %>
controller
def download
send_file '/home/blog/downloads/away.png',:type=>"application/png", :x_sendfile=>true
end
do this in route.rb
get "home/download_png" , as: :download
in view, change this
<%= link_to "DOWNLOAD", download_path %>
For the question,putting the images in /public would be fine. And for the error which you are getting,this is the problem
You are just putting the path of the image file in the link_to helper while it expects a route.
Try changing it to
<%= link_to "DOWNLOAD", home_download_png_url %>
Edit
Can't think why it didn't worked.Okay,as #nithinJ suggested you can use
<%= link_to "DOWNLOAD", "/diagram.png" %>
And as you mentioned,you want it to be downloded rather than opening in the new brower,you could do this in the controller
send_file '#{Rails.root}/public/diagram.png', type: 'image/png', disposition: 'attachment'
For more info,see send_file.

Rails download file from show action?

I have an uploader which allows you to upload documents. What I want to do is trigger a download for the document when you view its show action. The url would be something like:
/documents/16
This document could be .txt, or .doc.
So far, my show action looks like this:
def show
#document = Document.find(params[:id])
respond_with(#document) do |format|
format.html do
render layout: false, text: #document.name
end
end
end
How would I go about achieving this?
Take a look at the send_data method:
Sends the given binary data to the browser. This method is similar to render :text => data, but also allows you to specify whether the browser should display the response as a file attachment (i.e. in a download dialog) or as inline data. You may also set the content type, the apparent file name, and other things.
So, I think in your case it should be something like this:
def show
#document = Document.find(params[:id])
send_data #document.file.read, filename: #document.name
end
I created a new method in my controller for downloading a file. It looks like this. Stored_File is the name of the archived file and has a field called stored_file which is the name of the file. Using Carrierwave, if a user has the access/permissions to download the file, the URL will display and then send the file to the user using send_file.
Controller
def download
head(:not_found) and return if (stored_file = StoredFile.find_by_id(params[:id])).nil?
case SEND_FILE_METHOD
when :apache then send_file_options[:x_sendfile] = true
when :nginx then head(:x_accel_redirect => path.gsub(Rails.root, ''), :content_type => send_file_options[:type]) and return
end
path = "/#{stored_file.stored_file}"
send_file path, :x_sendfile=>true
end
View
<%= link_to "Download", File.basename(f.stored_file.url) %>
Routes
match ":id/:basename.:extension.download", :controller => "stored_files", :action => "download", :conditions => { :method => :get }

Ruby on rails file download link

I created file upload using paperclip! File uploads as it is supposed to.
Than I added file download method like this:
def download
sample = Sample.find(params[:id])
send_file upload.sample.path,
:filename => upload.sample_file_name,
:type => upload.sample_content_type,
:disposition => 'attachment'
flash[:notice] = "Your file has been downloaded"
end
But I cant figure out, what should I put in my show action so that I would be able to download the file?
I got as far as this:
<td><%= #sample.upload_file_name =%></td>
<%= link_to 'Download', :action => :download, :path =>#sample.upload.url, :type => #sample.upload_content_type %>
But it shows error : Couldn't find Sample with id=download
Can anyone help me?
Think you need to change your link_to to send the :id (that's what the controller action is looking for with params[:id])
<%= link_to 'Download', :action => :download, :id => #sample.id %>
Soz Karlis was writing as you posted :D
=link_to 'download', #sample.upload.path
This is the easiest way))
Assuming you set download named route properly, you can just say
<%= link_to 'Download', download_sample_path(#sample) %>
It looks like you have mismatch in your routes.
That is why, you have to:
Add additional route to your routes.rb for download action.
As it was said previously, you have to add link to your view (link_to).
Read this post for more advanced Download functionality:
http://thewebfellas.com/blog/2009/8/29/protecting-your-paperclip-downloads

Permalink-fu - Display URL differently

I'm using Ruby on Rails 2.3.8 and permalink-fu plugin. I would like to know how to generate permalinks like this: /posts/44444/this-is-the-title instead of /posts/44444-this-is-the-title
I've tried modifying my Post model as follows:
has_permalink :title, :update => true
def to_param
"#{permalink}"
end
And my routes file as follows:
map.show "/posts/:id/:permalink", :controller => 'posts', :action => 'show'
Then, if I manually type the url with that format, it will work, but if I make a link out of a post in my view as follows, it wont generate the link formatted that way:
<%= link_to p.title, p %>
Where p represents a post.
How can I do so when I call a post like that, I get a permalink formatted as /posts/:id/:permalink instead of /posts/:id-:permalink?
Try this one...
on model:
def to_params
[self.id, self.permalink]
end
on views:
<%= link_to p.title, show_path(p) %>

Resources