2011-07-05 83 views
0

我正在使用Prawn pdf庫但是我正在做一個複雜的設計,所以我需要一個快速的解決方案,以將html轉換爲pdf文件。Rails 2.3.8呈現一個html爲pdf

在此先感謝

+1

蝦使用wkhtmltopdf這是一個偉大的圖書館,即使是在待機獨自一人:自由而直挺。 – apneadiving

回答

1

我會與wicked_pdf紅寶石的寶石,它的自由結合使用wkhtmltopdf shell工具 ,並使用QtWebKit的渲染你的HTML到PDF。例如,還爲圖表執行JavaScript。你可以找到有關安裝的詳細信息:https://github.com/mileszs/wicked_pdf

+0

謝謝。我正在使用wicked_pdf rails插件。不過,我創建了一個新帖子。基本上我的問題是與頁眉和頁腳選項。我在Windows平臺上使用rails 2.3.8。 – maxiperez

0

我有一個已經使用PrinceXML生產了幾年的一個Rails應用程序。這是一個昂貴的 - 服務器許可證大約4K美元 - 但在PDF文件中呈現HTML + CSS做得非常好。我沒有看過較新的解決方案,因爲這個解決方案付費並且工作得很好。

對於它的價值,這裏的一些代碼,我適應from Subimage Interactive進行轉換簡單:

的lib/prince.rb

# Prince XML Ruby interface. 
# http://www.princexml.com 
# 
# Library by Subimage Interactive - http://www.subimage.com 
# 
# 
# USAGE 
# ----------------------------------------------------------------------------- 
# prince = Prince.new() 
# html_string = render_to_string(:template => 'some_document') 
# send_data(
#  prince.pdf_from_string(html_string), 
#  :filename => 'some_document.pdf' 
#  :type => 'application/pdf' 
# ) 
# 

class Prince 

    attr_accessor :exe_path, :style_sheets, :log_file 

    # Initialize method 
    # 
    def initialize() 
    # Finds where the application lives, so we can call it. 
    @exe_path = '/usr/local/bin/prince' 
    case Rails.env 
    when 'production', 'staging' 
     # use default hard-coded path 
    else 
     if File.exist?(@exe_path) 
     # use default hard-coded path 
     else 
     @exe_path = `which prince`.chomp 
     end 
    end 
    @style_sheets = '' 
    @log_file = "#{::Rails.root}/log/prince.log" 
    end 

    # Sets stylesheets... 
    # Can pass in multiple paths for css files. 
    # 
    def add_style_sheets(*sheets) 
    for sheet in sheets do 
     @style_sheets << " -s #{sheet} " 
    end 
    end 

    # Returns fully formed executable path with any command line switches 
    # we've set based on our variables. 
    # 
    def exe_path 
    # Add any standard cmd line arguments we need to pass 
    @exe_path << " --input=html --server --log=#{@log_file} " 
    @exe_path << @style_sheets 
    return @exe_path 
    end 

    # Makes a pdf from a passed in string. 
    # 
    # Returns PDF as a stream, so we can use send_data to shoot 
    # it down the pipe using Rails. 
    # 
    def pdf_from_string(string) 
    path = self.exe_path() 
    # Don't spew errors to the standard out...and set up to take IO 
    # as input and output 
    path << ' --silent - -o -' 

    # Show the command used... 
    #logger.info "\n\nPRINCE XML PDF COMMAND" 
    #logger.info path 
    #logger.info '' 

    # Actually call the prince command, and pass the entire data stream back. 
    pdf = IO.popen(path, "w+") 
    pdf.puts(string) 
    pdf.close_write 
    output = pdf.gets(nil) 
    pdf.close_read 
    return output 
    end 
end 

的lib/pdf_helper.rb

module PdfHelper 
    require 'prince' 

    private 
    def make_pdf(template_path, pdf_name, stylesheets = [], skip_base_pdf_stylesheet = false) 
     # application notices should never be included in PDFs, pull them from session here 
     notices = nil 
     if !flash.now[:notice].nil? 
     notices = flash.now[:notice] 
     flash.now[:notice] = nil 
     end 
     if !flash[:notice].nil? 
     notices = '' if notices.nil? 
     notices << flash[:notice] 
     flash[:notice] = nil 
     end 

     prince = Prince.new() 
     # Sets style sheets on PDF renderer. 
     stylesheet_base = "#{::Rails.root}/public/stylesheets" 
     prince.add_style_sheets(
     "#{stylesheet_base}/application.css", 
     "#{stylesheet_base}/print.css" 
    ) 
     prince.add_style_sheets("#{stylesheet_base}/pdf.css") unless skip_base_pdf_stylesheet 
     if 0 < stylesheets.size 
     stylesheets.each { |s| prince.add_style_sheets("#{stylesheet_base}/#{s}.css") } 
     end 

     # Set RAILS_ASSET_ID to blank string or rails appends some time after 
     # to prevent file caching, messing up local - disk requests. 
     ENV['RAILS_ASSET_ID'] = '' 
     html_string = render_to_string(:template => template_path, :layout => 'application') 
     # Make all paths relative, on disk paths... 
     html_string.gsub!("src=\"", "src=\"#{::Rails.root}/public") 
     html_string.gsub!("src=\"#{::Rails.root}/public#{::Rails.root}", "src=\"#{::Rails.root}") 

     # re-insert any application notices into the session 
     if !notices.nil? 
     flash[:notice] = notices 
     end 

     return prince.pdf_from_string(html_string) 
    end 

    def make_and_send_pdf(template_path, pdf_name, stylesheets = [], skip_base_pdf_stylesheet = false) 
     send_data(
     make_pdf(template_path, pdf_name, stylesheets, skip_base_pdf_stylesheet), 
     :filename => pdf_name, 
     :type => 'application/pdf' 
    ) 
    end 
end 

樣本控制器動作

include PdfHelper 
def pdf 
    index 
    make_and_send_pdf '/ads/index', "#{filename}.pdf" 
end