将Prawn pdf附加到电子邮件中

时间:2016-04-08 03:28:58

标签: ruby-on-rails actionmailer prawn

我一直在寻找年龄,我似乎仍然无法弄清楚这一点,

我目前正在使用prawn gem,我希望能够在pdf email中将invoice controllers附加到create action。我目前能够通过invoices/show从我的http://localhost:3000/invoices/297.pdf页面链接到生成的pdf,但我无法弄清楚如何将此pdf附加到电子邮件中。

目前我没有将生成的PDF存储在任何地方,我的邮件看起来像这样

邮件程序

class InvoiceMailer < ActionMailer::Base
default :from => "notifications@example.com"

 def invoice_email(user)
   @user = user
   mail(:to => user.email, :subject => "Invoice Recieved")
 end
end

我的InvoicesController创建动作

{...}
respond_to do |format|
  if @invoice.save
    InvoiceMailer.invoice_email(@invoice.user).deliver
    format.html { redirect_to invoice_url(@invoice, back_path: 
{...}

如何将我的发票添加为此邮件的附件?在我发送之前,是否需要将发票存放在某处?

2 个答案:

答案 0 :(得分:3)

如何执行此操作取决于PDF生成所需的时间和/或它对服务器的负载程度以及您是否关心它。在我的情况下,我是从用户生成的内容生成PDF,我看到一些PDF创建时间在30+秒范围内。解决这个问题变成了一个在线工作 - 其他地方和缓存 - 它(无论是数据库还是云存储)问题。

除了最简单的解决方案之外,@ toddmetheny建议云存储是完全正确的。如果您通过短暂存储托管诸如Heroku之类的东西,或者如果您将PDF创建与用户请求的电子邮件发送分开(例如,再次从Heroku,web dynos vs worker dynos),则会更有趣。您可以将PDF生成为本地临时文件,但是当您需要在“工作人员”上运行的邮件程序中读取该文件时,该临时文件可能不存在。

非常简单的选项

在您的邮件程序中,您可以将PDF生成为本地文件,将其读回内存,然后附加它:

def invoice_email(user)
  @user = user

  attachments['filename_for_user.pdf'] = generate_pdf_content

  mail(:to => user.email, :subject => "Invoice Recieved")
end

private

  # I had troubles trying to get Prawn to generate 'in memory'
  # so just write to, then read, then unlink a tempfile
  def generate_pdf_content
    pdf = some_method_that_generates_a_prawn_pdf_object
    Tempfile.create do |f|
      pdf.render_file f
      f.flush
      File.read(f)
    end
  end

我建议你从这里开始工作。

更复杂的选项

有一天,您可能希望将生成PDF(可能需要很长时间)的作业与发送电子邮件的作业分开,这通常要快得多。我这样做的方法是让一个生成PDF的作业到本地Tempfile,然后将该文件上传到S3存储并记录S3对象id(我在我的数据库中执行它,你可以将它作为一个作业属性你推动。)

完成后,该作业会创建新的邮件工作。邮件程序作业(可以在不同的服务器上执行)将PDF从S3存储下载到本地文件,然后将其添加到电子邮件中,就像上面的简单选项一样。

答案 1 :(得分:1)

您需要一个可以使用的网址。如果您不想将其存储在数据库中,则可以选择任何云存储解决方案。

以下是有关从rails guides on action mailer添加邮件附件的相关信息:

  

2.3.1添加附件

     

Action Mailer使添加附件变得非常容易。

     

传递文件名和内容,Action Mailer和Mail gem将自动猜测mime_type,设置编码并创建附件。

attachments['filename.jpg'] = File.read('/path/to/filename.jpg')
  

当触发邮件方法时,它将发送带有附件的多部分电子邮件,正确嵌套顶级为multipart / mixed,第一部分是包含纯文本和HTML电子邮件的multipart / alternative。 / p>