In my invoice system, I want a backup function to download all invoices at once in one zip file. This system is running on heroku - so it's only possible to save the pdfs temporary.
I've the rubyzip and wicked_pdf gem installed.
My current code in the controller:
def zip_all_bills
@bill = Bill.all
if @bill.count > 0
t = Tempfile.new("bill_tmp_#{Time.now}")
Zip::ZipOutputStream.open(t.path) do |z|
@bill.each do |bill|
@bills = bill
@customer = @bills.customer
@customer_name = @customer.name_company_id
t = WickedPdf.new.pdf_from_string(
render :template => '/bills/printing.html.erb',
:disposition => "attachment",
:margin => { :bottom => 23 },
:footer => { :html => { :template => 'pdf/footer.pdf.erb' } }
)
z.puts("invoice_#{bill.id}")
z.print IO.read(t.path)
end
end
send_file t.path, :type => "application/zip",
:disposition => "attachment",
:filename => "bills_backup"
t.close
end
respond_to do |format|
format.html { redirect_to bills_url }
end
end
This ends with the message IOError in BillsController#zip_all_bills closed stream
Here's how to do it: Put all of the PDF documents you want to compress (or just one) into a new folder. Right click on that folder. Select the “Send To” option and then click “Compressed (Zipped) folder.”
In the Preview app on your Mac, open the PDF that you want to compress. Choose File > Export. (Don't choose Export as PDF.) Click the Quartz Filter pop-up menu, then choose Reduce File Size.
Wicked PDF uses the shell utility wkhtmltopdf to serve a PDF file to a user from HTML. In other words, rather than dealing with a PDF generation DSL of some sort, you simply write an HTML view as you would normally, and let Wicked take care of the hard stuff.
I think what is wrong in your code is that you have t for your zip but you also also use it for individual pdfs. So I think when you try to use the tempfile for a pdf it is a problem because you are already using it for the zip.
But I don't think you need to use tempfiles at all (and I never actually got a tempfile solution working on Heroku)
Here is a controller method that works for me--also using wickedpdf and rubyzip on heroku. Note that I'm not using a Tempfile instead I'm just doing everything with StringIO (at least I think that's the underlying tech).
def dec_zip
require 'zip'
#grab some test records
@coverages = Coverage.all.limit(10)
stringio = Zip::OutputStream.write_buffer do |zio|
@coverages.each do |coverage|
#create and add a text file for this record
zio.put_next_entry("#{coverage.id}_test.txt")
zio.write "Hello #{coverage.agency_name}!"
#create and add a pdf file for this record
dec_pdf = render_to_string :pdf => "#{coverage.id}_dec.pdf", :template => 'coverages/dec_page', :locals => {coverage: coverage}, :layout => 'print'
zio.put_next_entry("#{coverage.id}_dec.pdf")
zio << dec_pdf
end
end
# This is needed because we are at the end of the stream and
# will send zero bytes otherwise
stringio.rewind
#just using variable assignment for clarity here
binary_data = stringio.sysread
send_data(binary_data, :type => 'application/zip', :filename => "test_dec_page.zip")
end
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With