我一直在寻找年龄,我似乎仍然无法弄清楚这一点,
我目前正在使用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:
{...}
如何将我的发票添加为此邮件的附件?在我发送之前,是否需要将发票存放在某处?
答案 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>