генерировать ZIP из сгенерированных PDF-файлов с помощью wicked_pdf

В моей системе счетов-фактур я хочу, чтобы функция резервного копирования загружала все счета сразу в один zip-файл. Эта система работает на heroku, поэтому PDF-файлы можно сохранять только временно.

У меня установлены гем rubyzip и wicked_pdf.

Мой текущий код в контроллере:

  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

Это заканчивается сообщением IOError в BillsController # zip_all_bills closed stream.


person Adrian    schedule 12.03.2013    source источник
comment
Привет, у меня точно такая же проблема, как и у вас. У меня есть вызывающее приложение, и я хочу сгенерировать ZIP из сгенерированных файлов PDF с помощью wicked_pdf. Я не могу найти правильного решения этой проблемы. Буду признателен за любые советы.   -  person Mateusz Urbański    schedule 05.09.2014


Ответы (1)


Я думаю, что ошибка в вашем коде в том, что у вас есть t для вашего zip-архива, но вы также используете его для отдельных PDF-файлов. Поэтому я думаю, что когда вы пытаетесь использовать временный файл для pdf, это проблема, потому что вы уже используете его для zip.

Но я не думаю, что вам вообще нужно использовать временные файлы (и у меня никогда не было решения для временных файлов, работающего на Heroku)

Вот метод контроллера, который мне подходит - также с использованием wickedpdf и rubyzip на heroku. Обратите внимание, что я не использую Tempfile, а просто делаю все с StringIO (по крайней мере, я думаю, что это основная технология).

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
person elc    schedule 19.11.2014