rails: create multiple download files from a controller#action? - ruby-on-rails

I would like to create 2 pdf documents from a single click.
I have it working with one file, but I can't seem to get to make 2 download files to happen w/out browser complaining about DoubleRenderError.
This is the code in my controller, where I am calling it twice and breaks. If I do it just once, everything works fine.
respond_to do |format|
format.pdf do
pdf = PrintCardsFront.new(paperSize, cardCount, #cards)
send_data pdf.render, filename: "cards_front_side.pdf", type: "application/pdf"
pdf = PrintCardsBack.new(paperSize, cardCount, #cards)
send_data pdf.render, filename: "cards_backside_side.pdf", type: "application/pdf"
end
end
(Rails 4.2)

You can only send one file in the HTTP Protocol.
Try to zip your two files and send them to the user.

Related

Rails downloads PDF instead of displaying it

In my Rails app I'm using Faraday to connect with 3rd party API. In one of the endpoint I'm downloading the pdf which means that the API will send me a binary file as a response. Now I want to display this pdf to the user, to make it work I've got below controller action:
def document
file = client.document(params[:id])
send_data(file, disposition: 'inline', type: 'application/pdf')
end
But instead of displaying the PDF, the download is started. What did I missed?
Found the solution, maybe it will be helpful for someone in the future.
All I need was to set Content-Disposition headers like below:
def document
file = client.document(params[:id])
send_data(file, disposition: 'inline', type: 'application/pdf', headers: { 'Content-Disposition' => 'inline' })
end

Invalid/damaged download using send_data with PowerPoint

I am generating a PowerPoint using the powerpoint gem and up until now I was using send_file, but now I want to use send_data. The reason for this is that send_data blocks the application from doing anything else until the call completes, while send_file allows the app to continue executing while the file downloads, which sometimes, due to coincidental timing, leads to the file being deleted before the user tells their browser to start the download and the web server finishes sending the file and thus a blank or incomplete file is downloaded.
This is how I create my PowerPoint:
#Creating the PowerPoint
#deck = Powerpoint::Presentation.new
# Creating an introduction slide:
title = 'PowerPoint'
subtitle = "created by #{username}"
#deck.add_intro title, subtitle
blah blah logic to generate slides
# Saving the pptx file.
pptname = "#{username}_powerpoint.pptx"
#deck.save(Rails.root.join('tmp',pptname))
Now, on to what I have tried. My first instinct was to call as follows:
File.open(Rails.root.join('tmp',"#{pptname}"), 'r') do |f|
send_data f.read, :filename => filename, :type => "application/vnd.ms-powerpoint", :disposition => "attachment"
end
I've also tried sending the #deck directly:
send_data #deck, :filename => pptname, :disposition => "attachment", :type => "application/vnd.ms-powerpoint"
Reading it ends with a larger file than expected and it isn't even able to be opened and sending the #deck results in a PowerPoint with one slide that simply has the title: #Powerpoint::Presentation:0x64f0dd0 (aka the powerpoint object).
Not sure how to get the object or file into binary format that send_data is looking for.
You need to open the file as binary:
path = #deck.save(Rails.root.join('tmp',pptname))
File.open(path, 'r', binmode: true) do |f|
send_data f.read, filename: filename,
type: "application/vnd.ms-powerpoint",
disposition: "attachment"
end
This can also be done by calling the #binmode method on instances of the file class.
send_data #deck, ...
Will not work since it calls to_s on the object. Since Powerpoint::Presentation does not implement a #to_s method you're getting the default Object#to_s.

Generate XML file and redirect to other view with Rails

I have a piece of code that generates an XML file. What I want to, and didn't find the solution, is to generate the XML file and ALSO redirect to another page, to give a feedback message.
My code is
def exportFiles
#files=FileToExport.getComponentToExport
recursive_tree= GitHubRepositorioService.getRecursiveTree('master')
GitHubService.updateFiles(#files, recursive_tree)
xml = Builder::XmlMarkup.new(:target=>$stdout, :indent=>2)
respond_to do |format|
format.xml { send_data render_to_string(:exportFiles), filename: 'exported_module.xml', type: 'application/xml', disposition: 'attachment' }
end
FileToExport.setComponentToExport(nil)
end
As I already use "respond_to" I can't use another redirect sentence... so, there is a way to generate (downloading) that file and redirect to other view?
Unfortunately, this is not possible via the controller as you can't send two responses.
But you could do this via javascript for instance. See this topic for more info Rails how do I - export data with send_data then redirect_to a new page?

How to save a Prawn generated PDF to the public folder?

I'm using Prawn gem to generate PDFs In my application...
app/controllers/orders.rb
class OrdersController < ApplicationController
...
def show
respond_to do |format|
format.html
format.pdf do
require "prawn/measurement_extensions"
...
#render pdf document
send_data pdf.render,
filename: "order_#{#order.id}.pdf",
type: 'application/pdf',
disposition: 'inline'
end
end
end
...
end
And It's working fine for displaying, But My questions are..
How to -Automatically- save those generated pdfs in the public folder (folder for each day) after a successful order creation? I've tried searching Prawn Documentation But I've found nothing.
How to show orders in only pdf format? I've Tried to Comment the format.html line but It didn't work
When you call pdf.render and send it to the client with send_data, you're actually dumping the contents of the pdf over the wire. Instead of that, you could dump the result of pdf.render in a file with File.new and use send_file in the controller. Check the documentation for File. Alternatively, you could attach the generated pdf to the specific order using something like Paperclip.
If you generate the pdf as a file in the server, you should use send_file instead of send_data. Read more about this in the guides.
You can use Prawn's render_file method to save the generated PDF to a file:
pdf.render_file(Rails.root.join('public', "order_#{#order.id}.pdf"))
See documentation: https://prawnpdf.org/docs/0.11.1/Prawn/Document.html

Creating PDFs with Prawn - missing attribute error

I'm working on PDF creation in my rails application. I found PDFkit didn't necessarily do what I wanted to do, so I figured I'd test out Prawn.
I added it to my controller using this code:
def show
#document = Document.find(params[:id])
respond_to do |format|
format.html
format.pdf do
pdf = Prawn::Document.new(#document)
send_data pdf.render, filename:"1",
type: "application/pdf",
disposition: "inline"
end
end
end
But using this I get a Missing Attribute error. I'm assuming this is because my model is also named Documents and conflicts with the Prawn::Document.new command?
Can I just not have a documents model and use Prawn - or is there something I'm missing here?
I don't think it's about Document vs Prawn::Document, but I've never seen someone pass an ActiveRecord instance to Prawn::Document.new. I think that expects an options hash, right? And calling render before giving it any content seems suspicious. What is the actual stack trace?

Resources