How do I display a PDF in ROR (Ruby)?

28,686

Solution 1

In your controller:

def pdf
  pdf_filename = File.join(Rails.root, "tmp/my_document.pdf")
  send_file(pdf_filename, :filename => "your_document.pdf", :type => "application/pdf")
end

In config/environment/production.rb:

config.action_dispatch.x_sendfile_header = "X-Sendfile" # for apache

or

config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for nginx

The config modification is required because it enables the web server to send the file directly from the disk, which gives a nice performance boost.

Update

If you want to display it instead of downloading it, use the :disposition option of send_file:

send_file(pdf_filename, :filename => "your_document.pdf", :disposition => 'inline', :type => "application/pdf")

If you want to display it inline, this question will be much more complete that I could ever be.

Solution 2

Basically you just need to write it in the html in your view. So this simple solution worked for me:

In the 'show.hmtl.erb'

<iframe src=<%= @certificate.certificate_pdf %> width="600" height="780" style="border: none;"> </iframe>

just putting the file location in embedded ruby as the source of the iframe tag worked for me after hours and hours of searching. 'certificate' is my model, and 'certificate_pdf' is my attachment file.

Solution 3

Depending where the PDF comes from, the following may help you. I have an application where I store a lot of things, and some of them have (additional) PDFs connected to the items. I store the items in the directory /public/res/<item_id>/. res means result, and item_id is the numeric id of that item in Rails.

In the view, I provide a link to the PDFs by the following (pseudo-)code as a helper method, that may be used in the view:

def file_link(key, name = nil)
  res= Ressource.find(:first, :conditions => ["key = ?", key])
  list = Dir["public/res/#{res.id}/*"]
  file= list.empty? ? "" : list[0]
  return file if file.empty?
  fn = name ? name : File.basename(file)
  link_to fn, "/res/#{res.id}/#{File.basename(file)}", :popup => true
end

The relevant part here is the link_to name, "/res/#{res.id}/#{File.basename(file)}" thing.

Solution 4

This may be too simple, but I had trouble finding a simple answer to my problem, so I'm posting it here. I really didn't want to add another action to my controller just to download a static file.

I just uploaded my file to S3 & used link_to referring to the path, which S3 provides after you upload the file and set the permissions (remember, everyone has to be able to upload and download it). I store lots of data for the app on S3 so it seemed like a fine choice.

<%= link_to "speaker registration form", "https://s3.amazonaws.com/gws_documents/speaker_registration.pdf" %>

Solution 5

def pdf
  pdf_content = ...# create the pdf
  send_data(pdf_content, :filename => "test.pdf", :type => "application/pdf")
end
Share:
28,686

Related videos on Youtube

IAmGroot
Author by

IAmGroot

I graduated from The University of Sheffield, and am currently work as a software engineer.

Updated on January 14, 2020

Comments

  • IAmGroot
    IAmGroot over 4 years

    I have looked around on the internet, but do not seem able to find how to display a PDF in rails (I can only find info on how to create one).

    Does anyone know what code/gem I need to display one?

    • lucapette
      lucapette over 12 years
      Use prawn is a sort of de-facto standard.
    • user1130176
      user1130176 over 5 years
      The hall monitors strike again. As of today 29 of us think this is a good question and 1 know it all says it's not but somehow had the authority to close it. SO is broken.
  • IAmGroot
    IAmGroot over 12 years
    hi, this looks promising but what if I just want to load and display from a file. I.e. I have no pdf_content variable.
  • Benoit Garret
    Benoit Garret over 12 years
    Two things to note about your solution: 1/ you can only display files that are in the public folder. 2/ You cannot change the name of the file in the browser save dialog.
  • mliebelt
    mliebelt over 12 years
    That is true, but sometimes sufficient. Its a simple solution, I know :-)
  • Benoit Garret
    Benoit Garret over 12 years
    You're perfectly right, I just wanted to point out the restrictions which may (or not ;-) ) be deal-breakers.
  • Matt
    Matt over 12 years
    In that case take a look at Benoit's solution.
  • IAmGroot
    IAmGroot over 12 years
    Hey this is great stuff. In terms of sending a pdf to the user. But what about displaying it on the website, before sending it ? :)
  • Benoit Garret
    Benoit Garret over 12 years
    Looks like my answer doesn't satisfy you, could you tell me why?
  • IAmGroot
    IAmGroot over 12 years
    sorry yes. Briefly adding the dispoition still wanted the user to download it. I havent added the iframe, but an example would be great on how to load a pdf inside such. :). I finished working yesterday not long after your reply, and was pre-engaged with a bug on other software since. Ive only very recently managed to successfully recieve the pdf over my webservice uncorrupted.
  • IAmGroot
    IAmGroot over 12 years
    Think ill stick to the easy, already implemented idea. for which you helped me with. thanks
  • JGutierrezC
    JGutierrezC over 10 years
    @BenoitGarret sorry for bother you, but, looks like File.join(Rails.root, "tmp/my_document.pdf") returns a string with the absolute path, for example: /home/user/rubyprojects/proj/assets/file.pdf, so, if it is an asset and i put 'assets/file.pdf' as the second parameter, It doesn't resolve it. How could i achieve that? Great answer by the way.
  • Benoit Garret
    Benoit Garret over 10 years
    @JGutierrezC The path is relative to the project root, does it work with File.join(Rails.root, "app/assets/file.pdf")?
  • JGutierrezC
    JGutierrezC over 10 years
    @BenoitGarret it works. But the path is /home/user/..., i think i didn't explain myself, my question is, shouldn't it be looking for http://127.0.0.1:3000/assets/file.pdf instead of a local folder? Thanks in advance man
  • Benoit Garret
    Benoit Garret over 10 years
    @JGutierrezC The sendfile header tells your web server to look for the file locally and send it directly to the client. You don't send the url to the client. This allows you to serve files even though they're not available in a public folder.
  • Benjamin Crouzier
    Benjamin Crouzier over 7 years
    This did it for me: send_file(..., disposition: 'inline')
  • Junaid Atique
    Junaid Atique almost 5 years
    this worked for me. using send_file(..., disposition: 'inline') plus using the route which generates the pdf will show pdf in iframe.