【问题标题】:Download PDFs from Prawn File in Zip从 Zip 中的虾文件下载 PDF
【发布时间】:2014-09-24 13:50:07
【问题描述】:

在我的 WebApp 中,我使用 Prawn 生成账单。

我想下载压缩文件中的所有账单!

我做到了:

def download
  bills = Bill.search(params[:q]).result(distinct: true).paginate(:page => params[:page], limit: 20, order: "paid_at DESC")

  bills.each do |b|
    Prawn::Document.generate("#{Rails.root}/public/pdfs/web_#{b.reference}.pdf")
  end


  require 'rubygems'
  require 'zip'
  zipfile_name = "#{Rails.root}/public/pdfs/factures.zip"
  Zip::File.open(zipfile_name, Zip::File::CREATE) do |zipfile|
    bills.each do |bill|
      zipfile.add("web_#{bill.reference}.pdf", "#{Rails.root}/public/pdfs/web_#{bill.reference}.pdf")
    end
  end

  path = File.join(Rails.root, "public", "pdfs")
  send_file File.join(path, "factures.zip")
end

但是 PDF 是空的,因为我没有指定允许生成 PDF 的“*.prawn”文件!

任何人都可以给我方法吗?

谢谢

编辑

我的show.pdf.prawn

prawn_document() do |pdf|


pdf.image "#{Rails.root}/app/assets/images/logo.jpg"
  pdf.move_down 30

  pdf.move_down 10
  pdf.text "<b>Email :</b> <a href='mailto:contact@mtaville.fr'>contact@mtaville.fr</a>", inline_format: true
  pdf.text "<b>Site :</b> <a href='http://www.mtaville.fr'>www.mtaville.fr</a>", inline_format: true

  pdf.move_up 230
  pdf.table [["Facture N° #{@bill.reference}"],["Date : #{ldate(@bill.paid_at, format: :short2)}"]], position: :right do
    cells.style do |c|
      c.background_color = "2857BE"
      c.text_color = "FFFFFF"
      c.border_color = "2857BE"
      c.align = :center
    end
  end

  pdf.move_down 30
  pdf.table [["CLIENT"]], position: :right do
    cells.style do |c|
      c.background_color = "2857BE"
      c.text_color = "FFFFFF"
      c.border_color = "2857BE"
      c.width = 280
    end
  end

  pdf.bounding_box([260, 600], :width => 280, :height => 80) do
    pdf.text "#{@bill.billable.name}", style: :bold
    pdf.text "#{@bill.billable.address_1} #{@bill.billable.address_2}"
    pdf.text "#{@bill.billable.zipcode} - <b>#{@bill.billable.town}</b>", inline_format: true
  end

  pdf.move_down 100
  pdf.text "<b>Objet :</b> Facture n° #{@bill.reference}", inline_format: true

  if @bill.billable_type == 'Subscription'
    pdf.move_down 10
    data = [
      ["Produit", "Prix unitaire HT", "Prix total HT"],
      ["Renouvellement de souscription à votre espace privé", "#{number_to_currency(@bill.total)}", "#{number_to_currency @bill.total}" ]
    ]
    pdf.table data, width: 540 do
      cells.style do |c|
        c.background_color = (c.row == 0)? "2857BE" : "ffffff"
        c.text_color = (c.row == 0)? "ffffff" : "000000"
        c.font_style = (c.row == 0)? :bold : :normal
      end
    end
  end
  if @bill.billable_type == 'Order'
    pdf.move_down 10
    data = [
      ["Produit", "Prix unitaire HT", "Prix total HT"],
      ["Annonce n°#{@bill.billable.ad.id}", "#{number_to_currency(@bill.total)}", "#{number_to_currency @bill.total}" ]
    ]
    pdf.table data, width: 540 do
      cells.style do |c|
        c.background_color = (c.row == 0)? "2857BE" : "ffffff"
        c.text_color = (c.row == 0)? "ffffff" : "000000"
        c.font_style = (c.row == 0)? :bold : :normal
      end
    end
  end

  pdf.move_down 20
  data = [
    ["Total HT", "#{number_to_currency(@bill.total)}" ],
    ["Total TVA #{@bill.tva}%", "#{number_to_currency(@bill.amount_vat)}"],
    ["Total TTC", "#{number_to_currency(@bill.amount_inclusive_of_tax)}"]
  ]
  pdf.table data, position: :right do
    cells.style do |c|
      c.font_style = (c.row % 2 == 0)? :bold : :normal
      c.width = 140
      c.align = (c.column == 1)? :right : :left
    end
  end

  pdf.move_down 20
  data = [["NET A PAYER", "#{number_to_currency(0)}"]]
  pdf.table data, position: :right do
    cells.style do |c|
      c.font_style = :bold
      c.background_color = "2857BE"
      c.text_color = "ffffff"
      c.width = 140
      c.align = (c.column == 1)? :right : :left
    end
  end

end

** 答案**

这是我的控制器中的功能:

def download
    bills = Bill.search(params[:q]).result(distinct: true).paginate(:page => params[:page], limit: 20, order: "paid_at DESC")

    require 'rubygems'
    require 'zip'
    require 'bill'
    zipfile_name = "#{Rails.root}/tmp/pdfs/factures.zip"
    Zip::File.open(zipfile_name, Zip::File::CREATE) do |zipfile|
      bills.each do |bill|
        temp_pdf = Tempfile.new("web_#{bill.reference}.pdf")
        temp_pdf.binmode
        temp_prawn_pdf = BillPdf.new(bill)
        temp_pdf.write temp_prawn_pdf.render
        temp_pdf.rewind
        zipfile.add("web_#{bill.reference}.pdf", "#{temp_pdf.path}")
        temp_pdf.close
      end
    end

    path = File.join(Rails.root, "tmp", "pdfs")
    send_file File.join(path, "factures.zip")
  end

还有我的班级:

class BillPdf < Prawn::Document
  include ActionView::Helpers::TranslationHelper
  include ActionView::Helpers::NumberHelper
  def initialize(bill)
    super()
    image "#{Rails.root}/app/assets/images/logo.jpg"

    move_down 10
    text "<b>N° TVA :</b> TVA", inline_format: true
    text "<b>Siret :</b> 789 618 691 00016", inline_format: true
    text "<b>Site :</b> <a href='http://www.mtaville.fr'>www.mtaville.fr</a>", inline_format: true

    move_up 230
    table [["Facture N° #{bill.reference}"],["Date : #{l(bill.paid_at, format: :short2)}"]], position: :right do
      cells.style do |c|
        c.background_color = "2857BE"
        c.text_color = "FFFFFF"
        c.border_color = "2857BE"
        c.align = :center
      end
    end

    move_down 30
    table [["CLIENT"]], position: :right do
      cells.style do |c|
        c.background_color = "2857BE"
        c.text_color = "FFFFFF"
        c.border_color = "2857BE"
        c.width = 280
      end
    end

    bounding_box([260, 600], :width => 280, :height => 80) do
      text "#{bill.billable.name}", style: :bold
      text "#{bill.billable.address_1} #{bill.billable.address_2}"
      text "#{bill.billable.zipcode} - <b>#{bill.billable.town}</b>", inline_format: true
    end

    move_down 100
    text "<b>Objet :</b> Facture n° #{bill.reference}", inline_format: true

    if bill.billable_type == 'Subscription'
      move_down 10
      data = [
        ["Produit", "Prix unitaire HT", "Prix total HT"],
        ["Renouvellement de souscription à votre espace privé", "#{number_to_currency(bill.total)}", "#{number_to_currency bill.total}" ]
      ]
      table data, width: 540 do
        cells.style do |c|
          c.background_color = (c.row == 0)? "2857BE" : "ffffff"
          c.text_color = (c.row == 0)? "ffffff" : "000000"
          c.font_style = (c.row == 0)? :bold : :normal
        end
      end
    end
    if bill.billable_type == 'Order'
      move_down 10
      data = [
        ["Produit", "Prix unitaire HT", "Prix total HT"],
        ["Annonce n°#{bill.billable.ad.id}", "#{number_to_currency(bill.total)}", "#{number_to_currency bill.total}" ]
      ]
      table data, width: 540 do
        cells.style do |c|
          c.background_color = (c.row == 0)? "2857BE" : "ffffff"
          c.text_color = (c.row == 0)? "ffffff" : "000000"
          c.font_style = (c.row == 0)? :bold : :normal
        end
      end
    end

    move_down 20
    data = [
      ["Total HT", "#{number_to_currency(bill.total)}" ],
      ["Total TVA #{bill.tva}%", "#{number_to_currency(bill.amount_vat)}"],
      ["Total TTC", "#{number_to_currency(bill.amount_inclusive_of_tax)}"]
    ]
    table data, position: :right do
      cells.style do |c|
        c.font_style = (c.row % 2 == 0)? :bold : :normal
        c.width = 140
        c.align = (c.column == 1)? :right : :left
      end
    end

    move_down 20
    data = [["NET A PAYER", "#{number_to_currency(0)}"]]
    table data, position: :right do
      cells.style do |c|
        c.font_style = :bold
        c.background_color = "2857BE"
        c.text_color = "ffffff"
        c.width = 140
        c.align = (c.column == 1)? :right : :left
      end
    end
  end

end

【问题讨论】:

  • 您可以使用Tempfile 生成一个临时文件并将其添加到压缩包中。确保在使用完文件后关闭该文件。
  • 好的,但是如何在该临时文件中添加内容?
  • 看我的回答,我已经扩展了这个想法。

标签: ruby-on-rails pdf prawn


【解决方案1】:

要进一步扩展我的评论,请参阅下面的代码重构。您可以使用Tempfiles,而不是将文件添加到您的公共目录(出于安全原因这是危险的)。您可能需要稍微调整一下,但应该为您提供Tempfiles 背后的基本概念。

def download
  bills = Bill.search(params[:q]).result(distinct: true).paginate(:page => params[:page], limit: 20, order: "paid_at DESC")

  require 'rubygems'
  require 'zip'
  zipfile_name = Tempfile.new(["#{Rails.root}/tmp/factures", '.zip'])
  Zip::File.open(zipfile_name, Zip::File::CREATE) do |zipfile|
    bills.each do |bill|
      temp_pdf = Tempfile.new(["basic_questions_#{Time.now.to_i}", '.pdf'])
      temp_pdf.binmode
      temp_prawn_pdf = Prawn::Document.new(#WHATEVER YOUR PARAMETERS ARE)
      temp_pdf.write temp_prawn_pdf.render
      temp_pdf.rewind
      zipfile.add("web_#{bill.reference}.pdf", "#{temp_pdf.path}")
      temp_pdf.close
    end
  end

  path = File.join(Rails.root, "public", "pdfs")
  send_file File.join(path, "factures.zip")
ensure
  zipfile_name.close
end

【讨论】:

  • 由于这可能需要很长时间,您可能希望将其移动到 delayed_job 或类似名称中。只要文件准备好,您就可以启动下载或发送文件准备好下载的 ajax。实际上,这完全取决于您的应用程序的构建范围以及最适合的范围。
  • 出于安全考虑。但是,我所有的 PDF 都是空白的!
  • temp_prawn_pdf = Prawn::Document.new(#WHATEVER YOUR PARAMETERS ARE) 行中,您需要将Prawn::Document..... 设置为PDF 生成器。例如,查看文档成功生成的其他代码并将该代码放在那里;修改任何必要的参数。
  • 这是一个非常大的文件!有没有办法引用那个文件??
  • 什么是大文件,生成文件的 Prawn 类,生成 PDF 的代码?您可以发布您的问题吗?
猜你喜欢
  • 2021-07-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-09-20
  • 2016-11-12
  • 1970-01-01
相关资源
最近更新 更多