在Rails3中,我使用WickedPDF gem
來呈現我的一個模型的PDF格式。這工作正常:/invoices/123
返回HTML,/invoices/123.pdf
下載PDF。從WickedPDF獲取PDF以通過Carrierwave進行附件
在我的Invoice模型中,我使用state_machine gem來跟蹤發票狀態。當發票從「未結帳」狀態變爲「已結帳」狀態時,我想要使用CarrierWave獲取發票PDF副本並將其附加到發票模型中。
我有三個部分分開工作:控制器創建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
UPDATE實測值的溶液中。
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
好吧,我有它的工作。第一步是圍繞WickedPDF忽略全局配置設置而不是在控制器上運行的事實。步驟2:使用Tempfile將PDF輸出保存爲二進制模式tempfile,然後將其附加到Carrierwave。編輯原始帖子以反映解決方案。 – lascarides
你可以給我更多關於第1步的細節嗎?我本地有一箇舊版本的wkhtmltopdf,用render_to_string導出就好了。在服務器上我有wkhtmltopdf 0.11.0和render_to_string的作品,但PDF是不可讀的。升級到0.11.0本地和render_to_string扼流圈..似乎是你有同樣的問題.. FYI:我使用'file = StringIO (render_to_string(options))'所以我可以跳過Tempfile。這是與回形針,但你可以試試看,如果你喜歡這個想法。 –
很高興你解決了它。你應該寫出你的解決方案作爲答案,然後接受你的答案。在回答你自己的問題時沒有傷害! – sockmonk