从Rails生成PDF

时间:2009-01-11 16:16:38

标签: ruby-on-rails pdf pdf-generation

促进 Rails PDF 生成的Ruby On Rails Wiki lists a couple of librarie。我需要打印出地址标签(字母格式,每页12-15个地址),不能决定使用哪一个。有什么建议吗?

10 个答案:

答案 0 :(得分:42)

答案 1 :(得分:9)

Prawnto肯定是Prawnto。 DSL是一种真正的享受,因为能够将PDF视为respond_to格式块中的任何其他格式的简单性:

respond_to do |format|
format.pdf { render :layout => false }

关于Prawn here的教程视频:

答案 2 :(得分:3)

还有RTeX。如果您愿意首先翻译为LaTeX,那么效果很好。 LaTeX是存储标记文档的一种非常好的方法。它只取决于每个文档的静态程度。如果大多数文档都是动态的,那么使用Prawn或PDF :: Writer可能会做得更好。如果大多数是静态的,每个只有几个文本替换,LaTeX可能是更好的选择。

答案 3 :(得分:2)

如果您没有做太复杂的事情,您还可以使用HTMLDOC,它将基本HTML转换为PDF。这可以防止您必须学习更多专有的布局语法(如Prawn的情况)。它可能会让你有些头痛:)

以下是HTMLDOC的ruby gem的链接:

此外,这是一个很好的指南,用于使用HTMLDOC将rails中的视图呈现为pdf:

答案 4 :(得分:2)

还有PDFKit。这也很有趣。

答案 5 :(得分:1)

我已经使用了PDF :: Writer和Prawn,并且发现Prawn使用起来更加愉快。查看Ruby Mendicant了解comparison,了解Prawn w / r / t PDF :: Writer的乐趣。

实际上,无论如何,只需查看Ruby Mendicant就可以获得一个伟大的design pattern作为开发人员的正确生计。

答案 6 :(得分:1)

虾是要走的路。现在用虾标签很容易做到。

在这里查看项目的自述文件:

https://github.com/jordanbyron/prawn-labels#readme

这是一个在Rails控制器中使用的超级简单示例。不要忘记将gem 'prawn-labels'添加到您的Gemfile中。

names = %w{Jordan Kelly Greg Bob}

labels = Prawn::Labels.render(names, :type => "Avery5160") do |pdf, name|
  pdf.text name
end

send_data labels, :filename => "names.pdf", :type => "application/pdf"

答案 7 :(得分:0)

虽然不是完全红宝石,但您可以使用OpenOffice .odt通过结合宁静和docsplit来生成PDF。

http://github.com/kremso/serenity

http://documentcloud.github.com/docsplit/

或者您可以使用使用odt和cups-pdf生成PDF的clamsy gem。

http://github.com/ngty/clamsy

答案 8 :(得分:0)

对于您的用例,我同意大多数其他答案prawn是正确的选择,因为您需要对输出进行像素级控制。

为了生成具有内置(固定)表格样式,标题等的PDF报告,您可以使用report gem - 请查看Generate pdf from Rails 3 - what tool to choose?以获取如何使用的示例。

答案 9 :(得分:0)

我从html使用飞碟进行pdf生成。它是一个java库,但您可以使用Ruby-Java Bridge gem在rails应用程序中访问它。它符合css 2.1并且有一些来自css3的附加功能,可以对分页进行一些额外的控制。我推荐它,因为它不要求你在你的html中加入'pdf code',你可以使用相同的视图和部分显示到浏览器,就像你生成pdfs一样。

飞碟:https://github.com/flyingsaucerproject/flyingsaucer

Ruby Java Bridge:http://rjb.rubyforge.org/

我使用此模块代码生成pdfs

require 'rubygems'
require 'rjb'

module Html2Pdf

  def self.included(controller)
      controller.send :helper_method, :create_pdf
  end

  def create_pdf(options = {})
      itext = "#{RAILS_ROOT}/lib/html2pdf/jars/iText-2.0.8.jar"
      core_renderer = "#{RAILS_ROOT}/lib/html2pdf/jars/core-renderer.jar"
      xerces = "#{RAILS_ROOT}/lib/html2pdf/jars/xml-apis-xerces-2.9.1.jar" 
      joinchar = (RUBY_PLATFORM.include? 'mswin') ? ';' : ':'
          classpath = [itext, core_renderer, xerces].join(joinchar)
      Rjb::load(classpath, jvmargs=['-Djava.awt.headless=true'])
      if options[:htmlstring].nil?
      options[:layout] ||= false
          options[:template] ||= File.join(controller_path,action_name+".pdf.erb")
          html_string = render_to_string(:template => options[:template], :layout => options[:layout])
    else
          html_string = options[:htmlstring]
    end
    # Make all paths relative, on disk paths...
    html_string.gsub!(".com:/",".com/") # strip out bad attachment_fu URLs
    html_string.gsub!( /src=["']+([^:]+?)["']/i ) { |m| "src=\"file:///#{RAILS_ROOT}/public/" + $1 + '"' } # re-route absolute paths
    html_string.gsub!( /url\(["']+([^:]+?)["']/i ) { |m| "url\(\"file:///#{RAILS_ROOT}/public/" + $1 + '"' } # re-route absolute paths
    # Remove asset ids on images with a regex // tbh i can't remember what this line is for but i'm sure it did something awesome
    html_string.gsub!( /src=["'](\S+\?\d*)["']/i ) { |m| 'src="' + $1.split('?').first + '"' } 
    filename = "#{RAILS_ROOT}/public/pdfs/"+options[:filename]+".pdf"
    fileOutputStream = Rjb::import('java.io.FileOutputStream')
      iTextRenderer = Rjb::import('org.xhtmlrenderer.pdf.ITextRenderer')
      renderer = iTextRenderer.new
      renderer.setDocumentFromString(html_string)
      os = fileOutputStream.new(filename)
      renderer.layout()
      renderer.createPDF(os)
      os.close()
  end

end

使用以下代码调用它:

def generate_pdf  
  htmlsrc = render_to_string(:partial => 'invoice', :layout => false)
  rnd = Time.now.to_s(:datentime).gsub!(/[\/ \.:]/,'')
  filename = "docstore/tmp_#{rnd}"
  create_pdf(:htmlstring => htmlsrc, :filename => filename)
  contents = open("#{RAILS_ROOT}/public/pdfs/#{filename}.pdf", "rb") { |io| io.read }
  File.delete("#{RAILS_ROOT}/public/pdfs/#{filename}.pdf")
  respond_to do | wants |
    wants.html { render :text => contents, :content_type => 'application/pdf' }
  end    
end