Generate PDF from Rails

前端 未结 10 1145
醉酒成梦
醉酒成梦 2020-12-02 06:36

The Ruby On Rails Wiki lists a couple of libraries that facilitate PDF generation in Rails. I need to print out address labels (in letter f

10条回答
  •  有刺的猬
    2020-12-02 07:08

    I've used flying saucer for pdf generation from html. It's a java library but you can use the Ruby-Java Bridge gem to access it in your rails app. It's css 2.1 compliant and has a few additions from css3 to allow some extra control over paging. I'd recommend it as it doesn't require you to put 'pdf code' in your html, you can use the same views and partials to display to the browser as you do to generate pdfs.

    Flying Saucer: https://github.com/flyingsaucerproject/flyingsaucer

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

    I use this module code to generate the 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
    

    Calling it with code like this:

    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
    

提交回复
热议问题