从WickedPDF获取PDF以通过Carrierwave进行附件 [英] Getting PDF from WickedPDF for attachment via Carrierwave

查看:84
本文介绍了从WickedPDF获取PDF以通过Carrierwave进行附件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

In Rails3, I am using the WickedPDF gem to render a PDF format of one of my models. This is working fine: /invoices/123 returns HTML, /invoices/123.pdf downloads a PDF.

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

In my Invoice model, I am using the state_machine gem to keep track of Invoice status. When an invoice goes from "unbilled" to "billed" state, I would like to grab a copy of the invoice PDF and attach it to the invoice model using CarrierWave.

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

I have the three parts working separately: the controller creates a PDF view, the model tracks state and triggers a callback when making the correct transition, and CarrierWave is set up properly. However, I'm having a heck of a time getting them to play nicely together.

如果我只是想获取发票的HTML版本,可以从模型中调用 render_to_string 。但是 render_to_string 似乎在接收PDF二进制文件时感到窒息。如果我可以找回数据流,则可以很容易地将数据写入临时文件并将其附加到上载器,但是我不知道如何获取数据流。

If I just wanted to grab the HTML version of the invoice, I could call render_to_string from the model. But render_to_string seems to choke on receiving a PDF binary file. If I can get a stream of data back, it's pretty easy to write that data to a tempfile and attach it to the uploader, but I can't figure out how to get the data stream.

有什么想法吗?下面的代码:

Any thoughts? Code below:

发票控制

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

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

这篇关于从WickedPDF获取PDF以通过Carrierwave进行附件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆