【问题标题】:Generating a PDF as attachment in a mail in Rails 4在 Rails 4 的邮件中生成 PDF 作为附件
【发布时间】:2014-02-13 19:08:11
【问题描述】:

问题

我想发送附有发票 PDF 的电子邮件。

我已经有了一个带有样式和 JavaScript 的发票显示视图​​。

javascript 正在计算总字段、格式化货币和日期并在分页符处拆分。

显示视图正在显示发票,就像它应该在 pdf 上一样。

尝试

  1. 我试过wicked_pdfpdfkit。问题是 这样做时..

    html = render_to_string(:action => "../invoices/show_pdf.html.erb") 
    mail(:to => @registration.billing_email, :subject => "Faktura") do |format|
      format.pdf do
        attachments['faktura.pdf'] = PDFKit.new(html).to_pdf
      end
    

    ..我没有浏览器来解释 javascript。所以所有 计算和格式不见了。当我在浏览器中打开 pdf 时,它是正确的。

  2. 我还尝试了shrimp,它使用 phantomjs 生成 PDF 的。这个解决方案的问题是我正在使用设计和 phantomjs 浏览器必须以某种方式登录。

我需要一些关于这个问题的优雅解决方案的建议。

要么

在我使用 pdfkit 或 wicked_pdf 生成 PDF 之前,使用所有 javascript 呈现视图的某种方式

如何将会话cookie分配给phantomjs?

我知道这是两个问题,但因为它解决了一个问题,我希望它没问题。

【问题讨论】:

    标签: javascript ruby-on-rails pdfkit wicked-pdf shrimp


    【解决方案1】:

    我认为shrimp 是你最好的选择。由于您需要执行 javascript,因此运行 PhantomJS 的解决方案可能是您可以采用的唯一方法。

    Shrimp 提供了一种在请求中添加会话 cookie 的简单方法。只是类似于以下内容:

    Shrimp::Phantom.new(url, options, {user_session: "a session"})
    

    正如您所理解的,initializer 接受一个选项散列,然后是一个带有您的 cookie 及其值的散列。

    现在最困难的部分是在您的服务器上始终有一个有效的会话来执行请求。根据您的会话管理(例如,您可能有自动过期),这可能有点棘手。


    编辑:根据 Shrimp 创建者的相关blog post 添加 Andreas 关于如何使用 Devise 在 Rails 应用程序中破解用户会话的发现:

    lib/devise/sign_in_interceptor.rb

    module Devise
      class SignInInterceptor
        def initialize(app, opts)
          @app    = app
          @scope  =opts[:scope]
          @secret = opts[:secret]
          @klass  = opts[:klass]
        end
    
        def call(env)
          if user = Rack::Request.new(env).cookies[@secret]
            env['warden'].session_serializer.store(@klass.constantize.find(user), @scope)
          end
    
          @app.call(env)
        end
      end
    end
    

    config/application.rb

    require File.expand_path('../../lib/devise/sign_in_interceptor', __FILE__)
    config.middleware.use Devise::SignInInterceptor, { :scope  => :user, :klass => 'User',
                                                        :secret => "our_very_very_long_secret" }
    

    通过这个设置,我们可以向我们的资源添加一个 to_pdf 方法 invoice.rb

    def to_pdf
      host        = Rails.env.production? ? 'www.adjust.io' : 'localhost:3000'
      url         = Rails.application.routes.url_helpers.reports_url(self, :host => host)
      cookie      = { 'our_very_very_long_secret' => user_id } #user_id is a instance method on the invoice class 
      options     = { :margin => "1cm"}
      res         = Shrimp::Phantom.new(url, options, cookie).to_pdf("#{Rails.root}/invoices/invoice_#{self.id}.pdf")
    end
    

    【讨论】:

    • 我尝试编辑您的答案以合并我的答案,但编辑被拒绝,因为“此编辑在原始帖子中更改太多;帖子的原始含义或意图将丢失。”为了将来参考,当我们只需要一个答案时,我真的不喜欢两个答案。在你的答案中编辑我的答案,我会接受你的。
    • 我在上面添加了您的发现。但是博客链接似乎返回 404。我希望它只是临时的。
    • 不正确。我已经修复了它,但仍然是 404,也许该网站由于某种原因已关闭。让我们将链接保留几天
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-30
    • 1970-01-01
    • 2020-12-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多