1

I implemented a show action to retrieve a pdf file url

 namespace :api do
   namespace :v2 do
     get '/patients/:id', to: 'patients#show'
   end
 end

http://localhost:3005/api/v2/patients/1894

{
    "id": 1894,
    "name": "Test",
    "file": {
        "url": "https://some-url-com"
    },
    "student_id": 20998,
    "created_at": "2019-07-02T13:27:10.975-04:00",
    "updated_at": "2019-07-02T13:54:53.248-04:00",
    ....
    ....
}

If a user accesses the show link then it should just return pdf file. I am trying to open pdf from the show endpoint. I tried following methods in controller but not having luck

patient = Patient.find(params[:id])
open(patient.file.url).read

also tried send_file

send_data patient.file.url, :type => "application/pdf", :disposition => 'attachment'

but not having luck. Is there any way I can have show url return pdf?

user18646557
  • 95
  • 2
  • 8
  • Does this work? https://stackoverflow.com/a/7500872/1880203 – Chiperific Aug 19 '22 at 02:12
  • I tried send_file(patient.file.url, filename: "your_document.pdf", disposition: 'inline', type: "application/pdf") but it returns error can not read file: https://some-url-com I am able to access pdf from https://some-url-com so not show it returns error. – user18646557 Aug 19 '22 at 02:25
  • That example uses a PDF already on disk. You'll need to fetch the file, then send it. – Chiperific Aug 19 '22 at 02:27
  • 1
    instead of `patient.file.url` you need a path/to/file.pdf on the server disk – Les Nightingill Aug 19 '22 at 02:31

2 Answers2

1

First, get the file:

require 'open-uri'

download = open('https://some-url-com')

IO.copy_stream(download, 'tmp/my_document.pdf')

Then send the file as part of your JSON:

pdf_filename = File.join(Rails.root, 'tmp/my_document.pdf')

# add this to your JSON where desired
send_file(pdf_filename, :filename => 'your_document.pdf', :type => 'application/pdf')
Chiperific
  • 4,428
  • 3
  • 21
  • 41
  • Thanks. When I tried that out I got error No such file or directory @ rb_sysopen - tmp/20998-5447fbc955.pdf at line IO.copy_stream(download, 'tmp/my_document.pdf') `download = open(patient.file.url) IO.copy_stream(download, "tmp/#{patient.file.file.filename}") pdf_filename = File.join(Rails.root, "tmp/#{patient.file.file.filename}") send_file(pdf_filename, filename: "tmp/#{patient.file.file.filename}", type: 'application/pdf')` – user18646557 Aug 19 '22 at 02:42
  • Do you have a 'tmp' folder inside your root folder? – Chiperific Aug 19 '22 at 02:48
  • Also, `join` allows you to do this: `File.join(Rails.root, tmp, patient.file.file.filename)` – Chiperific Aug 19 '22 at 02:50
  • Wouldn't it be: `File.join(Rails.root, tmp, patient.file.filename)` – Chiperific Aug 19 '22 at 02:51
  • After downloading the file, can you see the file in your 'tmp' folder? – Chiperific Aug 19 '22 at 02:52
  • 1
    There was a tmp folder earlier but I remember I deleted it in the morning but for some reason it didnt create it again. After creating it and trying out your answer I see it showed the pdf in postman. Thanks for your help. – user18646557 Aug 19 '22 at 02:57
  • It would be a good idea to have a check that the folder exists, and create it if it doesn't. Or use a different folder like 'public' because in production you need to make sure it's always there. You also might want to implement a way to delete the files from your server so they don't fill up the drive over time. – Chiperific Aug 19 '22 at 02:59
  • Yep. I was just checking about that to make sure tmp folder is there. – user18646557 Aug 19 '22 at 03:00
1

A simple way:

require "open-uri"

file = URI.open("https://some-url-com") # ruby 3+ must use URI.open

# it's a File (or Tempfile), you can do file things to it
# file       # => #<File:/tmp/open-uri20220818-414775-wdh4sb>
# file.path  # => /tmp/open-uri20220818-414775-wdh4sb
# file.read  # => "%PDF-1.5\n%\xE4\xF0\xED\xF8\n8 ..."

send_data file.read, type: "application/pdf"
# or
send_file file.path, type: "application/pdf"
Alex
  • 16,409
  • 6
  • 40
  • 56