Download Image attached using Paperclip - ruby-on-rails

Is there a way to make the users download the images attached using paperclip?
I just made a link like this:
link_to 'imagename', image.attachment.url
But this makes the browser open the image. I want the browser to ask the user to save the image. Is there a way to do that?

When it comes to sending a file you can find all information in here http://api.rubyonrails.org/classes/ActionController/Streaming.html There are most important cuts:
Simple download:
send_file '/path/to.zip'
Show a JPEG in the browser:
send_file '/path/to.jpeg', :type => 'image/jpeg', :disposition => 'inline'
Show a 404 page in the browser:
send_file '/path/to/404.html', :type => 'text/html; charset=utf-8', :status => 404
to use one of this option you have to create a new action in controller like this:
class SomeController < ApplicationController
def download_file
send_file image.attachment.path
end
end

Here's a simple solution using the HTML5 download attribute
<%= link_to image.name, image.attachment.url, download: image.attachment.original_filename %>

Related

open a url link in a new tab from a Rails controller

I've been trying to open multiple pdf's in new tabs automatically from my rails controller, but nothing has worked so far so I'm back to square one. If anyone could help, it would be much appreciated! Below is an example of what I'm trying to do.
id_array = [1,2,3]
id_array.each do |id|
// I want to open each of these three links in a new browser tab
http://localhost:3000/pdf/id.pdf
end
Cheers!
Can open files in new browser window using send_file method. Use :disposition => 'inline'
Eg: send_file "#{Rails.root}/pdf/id.pdf",:filename => 'id.pdf', :type => 'application/pdf', :disposition => 'inline'
you should respond with a javascript file.
<% id_array.each do |id| %>
window.open('<%= "http://localhost:3000/pdf/#{id}.pdf" %>', '_blank');
<% end %>

Allowing User to Download Image from my S3 Bucket

I am trying to construct a method which will allow a user to download a pdf file from my s3 bucket, (which at the moment it does)
But some parts of the url may change from time to time, like the id number after /timetables, the filename (but will always be a pdf) and the id number after the filename
This is what i have so far
def download
path = "images/timetables/14/original.pdf?"
data = open("http://#{ENV['AWS_BUCKET']}.s3.amazonaws.com/#{path}/1392904333")
send_data data.read, filename: 'Timetable',
type: 'application/pdf',
disposition: 'attachment',
stream: 'true',
buffer_size: '4096'
end
is there a way to get this information on the fly or can i only hardcode it? Ideally i want to store as much as the path into variables as i can.
Could anyone show me how to do this correctly please.
Thanks
It'll be easier to use paperclip to manage the uploading. Using this you'll create a table to save a record which will have a dynamic reference to your uploaded file on S3.
The workflow goes like this:
You upload the PDF in question to your app
paperclip uploads it to S3 and saves the URL to your database
you provide a link to your users for the S3 URL of the PDF
OR you give them the link to your record and you initiate the download as you posted above
First the model which will hold the pdf file reference looks like this:
class PdfRecord < ActiveRecord::Base
has_attached_file :pdf, :storage => :s3,
:bucket => 'S3_BUCKET_NAME',
:s3_credentials => {
:access_key_id => 'AWS_ACCESS_KEY_ID',
:secret_access_key => 'AWS_SECRET_ACCESS_KEY'
}
end
Create a form for yourself to upload your pdf:
# app/views/pdf_records/new
<%= form_for #pdf_record, multipart: true do |f| %>
<%= f.label :pdf %>
<%= f.file_field :pdf %>
<%= f.submit %>
<% end %>
Using this form you can upload the pdf and paperclip will save it to S3 and keep a reference to it in your database.
Give your users a link to your pdf_record like this:
#pdf_record = PdfRecord.find(which ever one you want)
#pdf_record.pdf.url # => the S3 url
Giving your users that url will let them download the pdf directly however, if you want to hide the URL and also allow you to update the pdf without breaking the link you can give the users a link to the pdf_record and then you initiate the download from your controller:
# give your users this url, as defined in your routes.rb
pdf_record_url(#pdf_record)
Then in the show action of the pdf_record controller:
def show
pdf_record = PdfRecord.find(params[:id])
data = open(pdf_record.pdf.url)
send_data data.read, filename: pdf_record.pdf_file_name,
type: pdf_record.pdf_content_type,
disposition: 'attachment',
stream: 'true',
buffer_size: '4096'
end
Now, you can update that pdf_record whenever you want and since your users have a link to the record rather than the actual pdf file the link will always work.

Rails download http response/displayed site

Instead of displaying the xml file rendered by the index.api.rsb file in my browser, i want to download it. To me this sounds very simple, but I cant find a solution.
I tried the following in the controller-method:
def split
if params[:export] == "yes"
send_file *here comes the path to xml view*, :filename => "filename", :type => :xml
end
respond_to ...
end
The result is a MissingFile exception...
Thanks in advance
Note that :disposition for send_file defaults to 'attachment', so that shouldn't be a problem.
If you have a MissingFile exception, that means the path is incorrect. send_file expects the path to an actual file, not a view that needs to be rendered.
For your case, render_to_string might be what you need. Refer to this related question. It renders the view and returns a string instead of setting the response body.
def split
if params[:export] == "yes"
send_data(render_to_string path_to_view, filename: "object.xml", type: :xml)
end
end
To force it to download it, add :disposition => attachment to your send_file method.
Source: Force a link to download an MP3 rather than play it?

When using redirect_to files on s3. How to either display an image or download a file

In Rails 3 AttachmentsController, I have the following:
def show
attachment = Attachment.find_by_id(params[:id])
redirect_to(attachment.authenticated_url())
end
Where authenticated_url is simply a URL to S3 to access the file.
The problem is that the file is always downloaded by the browser. What I would like to have happen is if the file is an image/pdf, something the browser can render, show the file in the browser and only download non-browser friendly files.
Have you seen this before? Any ideas on where to start?
Thanks
send_file can be used for remote url as well
file = open("http://cdn2.example.com/somefile.pdf")
send_file(file, :filename => "example.pdf", :type => "application/pdf" , :disposition => "attachment")
Here example.pdf will be downloaded. If you want open pdf in browser itself use this
file = open("http://cdn2.example.com/somefile.pdf")
send_file(file, :filename => "example.pdf", :type => "application/pdf" , :disposition => "inline")
redirect_to #attachment.url
I'm using Paperclip as well, and this display pictures inside the browser. Do you have to do something different than this?
I think you'll want to look into the rails send_file method.
1) http://apidock.com/rails/ActionController/DataStreaming/send_file
The :disposition option lets you decide whether a file will be downloaded or displayed inline. I used this in my rails app to let users download mp3 files.
Hope this helps.

Showing images with carrierwave in rails 3.1 in a private store folder

I have a rails 3.1 app and I am adding carrierwave to store images. But I want to store those images outside the public folde,r because they should only be accessible when users are loaded in the app. So I changed the store_dir in carrerwave with the initializer file:
CarrierWave.configure do |config|
config.root = Rails.root
end
And my carrierwave uploader goes like this:
class ImageUploader < CarrierWave::Uploader::Base
...
def store_dir
"imagenes_expedientes/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
Images are stored correctly and if I use the public folder everything works fine. However when trying to move things to the private folder, images are not displayed and when I try to open them in a new window I get the following error:
Routing Error
No route matches [GET] "/imagenes_expedientes/volunteer/avatar/15/avatar.jpg"
I was trying to deliver the files using send_file through the controller, but instead of loading the page I only get the image downloaded.
def show
send_file "#{Rails.root}/imagenes_expedientes/avatar.jpg", :type=>"application/jpg", :x_sendfile=>true
end
Finally Images are displayed like this in the views:
<%= image_tag(#volunteer.avatar_url, :alt => "Avatar", :class => "avatar round") if #volunteer.avatar? %>
This may probably be solved rather easy, but since I am somehow new to Rails, I donĀ“t know what to do it. Should I set a route? Or is there anyway to display the images using the send_file method?
Thanks!
ANSWER
I managed to display images using x-sendfile and putting :disposition => 'inline' as suggested by clyfe. I made a new action in my controller:
def image
#volunteer = Volunteer.find(params[:id])
send_file "#{Rails.root}/imagenes_expedientes/#{#volunteer.avatar_url}",:disposition => 'inline', :type=>"application/jpg", :x_sendfile=>true
end
Added to the routes:
resources :volunteers do
member do
get 'image'
end
end
And displayed in the views:
<%= image_tag(image_volunteer_path(#volunteer), :alt => "Avatar", :class => "avatar round") if #volunteer.avatar? %>
Hope it helps others!
:disposition => 'inline' will make your images display in the browser instead of popping up the download dialog.
def show
send_file "#{Rails.root}/imagenes_expedientes/avatar.jpg", :disposition => 'inline', :type=>"application/jpg", :x_sendfile=>true
end
Depending on the images sizes and the number of users you might want to move this action to a metal app, or a separate so as to not block the server.

Resources