从WickedPDF获取PDF以通过Carrierwave进行附件

在Rails3中,我使用WickedPDF gem来渲染我的一个模型的PDF格式。 这工作正常: /invoices/123返回HTML, /invoices/123 /invoices/123.pdf下载PDF。

在我的发票模型中,我使用state_machine gem来跟踪发票状态。 当发票从“未开单”状态变为“开票”状态时,我想获取发票PDF的副本并使用CarrierWave将其附加到发票模型。

我将这三个部分分开工作:控制器创建PDF视图,模型跟踪状态并在进行正确转换时触发回调,并正确设置CarrierWave。 但是,我有一段时间让他们一起玩得很好。

如果我只是想获取发票的HTML版本,我可以从模型中调用render_to_string 。 但是render_to_string似乎在接收PDF二进制文件时窒息。 如果我可以获得数据流,那么将这些数据写入临时文件并将其附加到上传器非常容易,但我无法弄清楚如何获取数据流。

有什么想法吗? 代码如下:

发票控制器

 def show @invoice = @agg_class.find(params[:id]) respond_to do |format| format.pdf do render_pdf end format.html # show.html.erb format.json { render json: @aggregation } end end 

 def render_pdf(options = {}) options[:pdf] = pdf_filename options[:layout] = 'pdf.html' options[:page_size] = 'Letter' options[:wkhtmltopdf] = '/usr/local/bin/wkhtmltopdf' options[:margin] = { :top => '0.5in', :bottom => '1in', :left => '0in', :right => '0in' } options[:footer] = { :html => { :template => 'aggregations/footer.pdf.haml', :layout => false, } } options[:header] = { :html => { :template => 'aggregations/header.pdf.haml', :layout => false, } } render options end 

Invoice.rb

 def create_pdf_copy # This does not work. pdf_file = ApplicationController.new.render_to_string( :action => 'aggregations/show', :format => :pdf, :locals => { :invoice => self } ) # This part works fine if the above works. unless pdf_file.blank? self.uploads.clear self.uploads.create(:fileinfo => File.new(pdf_file), :job_id => self.job.id) end end 

更新找到解决方案。

 def create_pdf_copy wicked = WickedPdf.new # Make a PDF in memory pdf_file = wicked.pdf_from_string( ActionController::Base.new().render_to_string( :template => 'aggregations/show.pdf.haml', :layout => 'layouts/pdf.html.haml', :locals => { :aggregation => self } ), :pdf => "#{self.type}-#{self}", :layout => 'pdf.html', :page_size => 'Letter', :wkhtmltopdf => '/usr/local/bin/wkhtmltopdf', :margin => { :top => '0.5in', :bottom => '1in', :left => '0in', :right => '0in' }, :footer => { :content => ActionController::Base.new().render_to_string({ :template => 'aggregations/footer.pdf.haml', :layout => false }) }, :header => { :content => ActionController::Base.new().render_to_string({ :template => 'aggregations/header.pdf.haml', :layout => false }) } ) # Write it to tempfile tempfile = Tempfile.new(['invoice', '.pdf'], Rails.root.join('tmp')) tempfile.binmode tempfile.write pdf_file tempfile.close # Attach that tempfile to the invoice unless pdf_file.blank? self.uploads.clear self.uploads.create(:fileinfo => File.open(tempfile.path), :job_id => self.job.id) tempfile.unlink end end 

解:

 def create_pdf_copy wicked = WickedPdf.new # Make a PDF in memory pdf_file = wicked.pdf_from_string( ActionController::Base.new().render_to_string( :template => 'aggregations/show.pdf.haml', :layout => 'layouts/pdf.html.haml', :locals => { :aggregation => self } ), :pdf => "#{self.type}-#{self}", :layout => 'pdf.html', :page_size => 'Letter', :wkhtmltopdf => '/usr/local/bin/wkhtmltopdf', :margin => { :top => '0.5in', :bottom => '1in', :left => '0in', :right => '0in' }, :footer => { :content => ActionController::Base.new().render_to_string({ :template => 'aggregations/footer.pdf.haml', :layout => false }) }, :header => { :content => ActionController::Base.new().render_to_string({ :template => 'aggregations/header.pdf.haml', :layout => false }) } ) # Write it to tempfile tempfile = Tempfile.new(['invoice', '.pdf'], Rails.root.join('tmp')) tempfile.binmode tempfile.write pdf_file tempfile.close # Attach that tempfile to the invoice unless pdf_file.blank? self.uploads.clear self.uploads.create(:fileinfo => File.open(tempfile.path), :job_id => self.job.id) tempfile.unlink end end 

有一种更好的方法: 没有控制器的Rails中的PDF 。