combine_pdf not combining the pdfs - ruby-on-rails

I think I am missing something simple. Using combine_pdf: I am attempting to combine two pdf files into one pdf, and then send that resulting pdf with send_data in my rails app.
Here is my code in a controller:
pdf = CombinePDF.new
# returns an array, each element is a string of an absolute path
# to the file I want to upload
absolute_upload_paths = #obj.attachments.collect {|obj| obj.my_attachment.path}
absolute_upload_paths.each {|upload_path| pdf << CombinePDF.load(upload_path)}
send_data pdf, filename: “my_combined_pdf”, type: "application/pdf"
What results is that a damaged pdf file gets sent which cannot be opened:
Adobe Acrobat Reader could not open 'VR_Voc_Eval-51.pdf' because it is either not a supported file type or because the file has been damaged (for example, it was sent as an email attachment and wasn't correctly decoded).
What am I missing? How can I use this gem to combine two existing pdf files into one pdf and then send it to the user?

It looks like the README for that library calls .to_pdf when sending the data. Hopefully calling #to_pdf on the pdf object like in the example will fix your issue.
send_data pdf.to_pdf, filename: “my_combined_pdf”, type: "application/pdf"
https://github.com/boazsegev/combine_pdf#rendering-pdf-data

Related

PDF file generated by Prawn throws "Failed - server error" when I try to download it from the browser's pdf viewer

I have a PDF file that is generated in ruby on rails with Prawn.
I used send_file with disposition: inline.
pdf = <A method is called to generate the PDF>
pdf.render_file file_path # file_path = public/assets/reports/test_report.pdf
send_file(file_path, filename: 'test_report.pdf', type: 'application/pdf', disposition: 'inline')
The pdf is displayed as expected but when I try to download it from the browser's pdf viewer after the pdf is displayed, it throws me an error saying "failed - server error".
Download button
error
Has anyone faced this issue or have a possible solution to it?
Tried using send_data instead of send_file the issue still remains. I have tried searching through the internet including stack overflow, didn't find a proper solution. I went through PrawnRails documentation, no luck there too.

How to handle when API returns PDF binary stream

I have an e-signature tool I'm using and when I want to download the executed file, it's a simple GET request. The issue is that it:
Returns PDF file binary stream of the document which you can save as PDF file.
When examining the file it looks something like this (this is only a snippet):
> r.body
=> "%PDF-1.4\n%\xE2\xE3\xCF\xD3\n77 0 obj\n<</ByteRange [0 141 16527 447870 ] /ContactInfo()/Contents <30820ffe06092a864886f70d010702a0820fef30820feb020101310f300d06096086480165030402010500300b06092a864886f70d010701a0820e393082042a30820312a00302010202043863def8300d06092a864886f70d01010505003081b431143012060355040a130b456e74727573742e6e65743140303e060355040b14377777772e656e74727573742e6e65742f4350535f3230343820696e636f72702e206279207265662e20286c696d697473206c6961622e2931253023060355040b131c286329203139393920456e74727573742e6e6574204c696d69746564313330310603550403132a456e74727573742e6e6574204365727469666963
What can I do with this data to present it on the screen as a PDF?
You can use send_data, this will download the file or open it in the browser depending on which browser your user is using:
send_data(r.body, type: 'application/pdf', disposition: 'attachment', filename: 'file.pdf')
See further: https://apidock.com/rails/ActionController/Streaming/send_data

How to convert Base64 string to pdf file using prawn gem

I want to generate pdf file from DB record. Encode it to Base64 string and store it to DB. Which works fine. Now I want reverse action, How can I decode Base64 string and generate pdf file again?
here is what I tried so far.
def data_pdf_base64
begin
# Create Prawn Object
my_pdf = Prawn::Document.new
# write text to pdf
my_pdf.text("Hello Gagan, How are you?")
# Save at tmp folder as pdf file
my_pdf.render_file("#{Rails.root}/tmp/pdf/gagan.pdf")
# Read pdf file and encode to Base64
encoded_string = Base64.encode64(File.open("#{Rails.root}/tmp/pdf/gagan.pdf"){|i| i.read})
# Delete generated pdf file from tmp folder
File.delete("#{Rails.root}/tmp/pdf/gagan.pdf") if File.exist?("#{Rails.root}/tmp/pdf/gagan.pdf")
# Now converting Base64 to pdf again
pdf = Prawn::Document.new
# I have used ttf font because it was giving me below error
# Your document includes text that's not compatible with the Windows-1252 character set. If you need full UTF-8 support, use TTF fonts instead of PDF's built-in fonts.
pdf.font Rails.root.join("app/assets/fonts/fontawesome-webfont.ttf")
pdf.text Base64.decode64 encoded_string
pdf.render_file("#{Rails.root}/tmp/pdf/gagan2.pdf")
rescue => e
return render :text => "Error: #{e}"
end
end
Now I am getting below error:
Encoding ASCII-8BIT can not be transparently converted to UTF-8.
Please ensure the encoding of the string you are attempting to use is
set correctly
I have tried How to convert base64 string to PNG using Prawn without saving on server in Rails but it gives me error:
"\xFF" from ASCII-8BIT to UTF-8
Can anyone point me what I am missing?
The answer is to decode the Base64 encoded string and either send it directly or save it directly to disk (naming it as a PDF file, but without using prawn).
The decoded string is a binary representation of the PDF file data, so there's no need to use Prawn or to re-calculate the content of the PDF data.
i.e.
raw_pdf_str = Base64.decode64 encoded_string
render :text, raw_pdf_str # <= this isn't the correct rendering pattern, but it's good enough as an example.
EDIT
To clarify some of the information given in the comments:
It's possible to send the string as an attachment without saving it to disk, either using render text: raw_pdf_str or the #send_data method (these are 4.x API versions, I don't remember the 5.x API style).
It's possible to encode the string (from the Prawn object) without saving the rendered PDF data to a file (save it to a String object instead). i.e.:
encoded_string = Base64.encode64(my_pdf.render)
The String data could be used directly as an email attachment, similarly to the pattern provided here only using the String directly instead of reading any data from a file. i.e.:
# inside a method in the Mailer class
attachments['my_pdf.pdf'] = { :mime_type => 'application/pdf',
:content => raw_pdf_str }

Serving excel sheet (.xls) to browser for download using rails & angular

I am using spreadsheet gem to generate .xls file. After writing it to a file, I am trying to send to client browser for download.
Below is the code in rails
workbook = Spreadsheet::Workbook.new
# Constructed the data
file = "/path/to/file/sheet.xls"
workbook.write file
send_file file
This file when opened contains expected data in ideal format.
Below is the code in js:
CustomRestService.custom_post("report",{report_data: angular.toJson($scope.report_data)},"download_xls",{}).then (data)->
if data
hiddenElement = document.createElement('a')
angular.element(document.body).append(hiddenElement)
hiddenElement.href = 'data:attachment/xls,' + encodeURI(data)
hiddenElement.target = '_blank'
hiddenElement.download = "report.xls"
hiddenElement.click()
hiddenElement.remove()
But the file getting downloaded in browser contains junk data. I tried multiple solutions like below:
Using send_data, instead of send_file
Generated xls data and wrote to StringIO object to directly download
Constructed Blob object in js, with type as "application/vnd.ms-excel" and trying to download it.
All attempts failed, as I am missing something. All suggestions are welcome.
filename = "/path/to/file/sheet.xls"
tempfile = Tempfile.new(filename)
workbook = Spreadsheet::Workbook.new
...
workbook.write(tempfile.path)
send_file tempfile.path, :filename => filename

Rails send_data passes plain text path as file

I cant figure out what Im doing wrong here. Im using Carrierwave to allow users to upload PDF files to AWS. So far upload and record creation go off without a hitch and when browsing the S3 bucket Im able to download and read the file no problem.
The issue Im having is with the "send_data" function in my controller The file download is being triggered, but instead of the PDF thats in AWS im getting a txt file(with PDF extension), that contains only the path to the file.
here is my code, hopefully more experienced eyes will spot my error.
send_data #document.file.url.to_s, :type => "application/pdf", :disposition => "attachment", :filename => #document.title.to_s
Look at semantic for those methods:
send_data(data, options = {})
send_file(path, options = {})
For send_data() you should open and read the file, for send_file() you can use just a path to file.
send_data(File.read(#document.file.url.to_s), type: "application/pdf", disposition: "attachment", filename: #document.title.to_s)

Resources