我正在使用Prawn从我的控制器生成PDF,当直接在网址上访问时,它可以完美地运行,I.E。本地主机:3000 /响应/次数1.pdf
但是,当我尝试动态生成此文件以包含在Mailer中时,所有内容都会冻结并且超时。
我已尝试过各种方法来生成/附加文件,但没有一种方法改变了结果。
我也尝试修改Net :: HTTP的超时无效,只需要LONGER超时。
如果我在Rails控制台上运行此命令,则会收到PDF数据流。
Net::HTTP.get('127.0.0.1',"/responses/1.pdf", 3000)
但如果我在控制器中包含此代码,则会超时。
我尝试了两种不同的方法,并且都反复失败。
方法1 控制器:
http = Net::HTTP.new('localhost', 3000)
http.read_timeout = 6000
file = http.get(response_path(@response, :format => 'pdf')) #timeout here
ResponseMailer.confirmComplete(@response,file).deliver #deliver the mail!
方法1梅勒:
def confirmComplete(response,file)
email_address = response.supervisor_id
attachments["test.pdf"] = {:mime_type => "application/pdf", :content=> file}
mail to: email_address, subject: 'Thank you for your feedback!'
end
以上代码超时。
方法2控制器:
ResponseMailer.confirmComplete(@response).deliver #deliver the mail!
方法2梅勒:
def confirmComplete(response)
email_address = response.supervisor_id
attachment "application/pdf" do |a|
a.body = Net::HTTP.get('127.0.0.1',"/responses/1.pdf", 3000) #timeout here
a.filename = "test.pdf"
end
mail to: email_address, subject: 'Thank you for your feedback!'
端
如果我切换a.body和a.filename,它首先会出错
undefined method `filename=' for #<Mail::Part:0x007ff620e05678>
我发现的每个示例都有不同的语法或建议,但没有解决Net :: HTTP超时的问题。 Rails 3.1,Ruby 1.9.2
答案 0 :(得分:2)
问题在于,在开发过程中,您只运行一个服务器进程,该进程正忙于生成电子邮件。该过程正在发送另一个请求(自身)以生成PDF并等待响应。对PDF的请求基本上是在服务器上排队,以便它可以获得它的PDF,但服务器正忙于生成电子邮件并等待获取PDF才能完成。因此,你永远等待。
您需要做的是启动第二个服务器进程...
script/rails server -p 3001
然后通过类似......
获取PDFargs = ['127.0.0.1','/responses/1.pdf']
args << 3001 unless Rails.env == 'production'
file = Net::HTTP.get(*args)
顺便说一句,根据您在生产计算机上运行的服务器,您可能会遇到指向127.0.0.1的问题。您可能需要在生产中将其设置为动态并指向完整域,但这应该很容易。
答案 1 :(得分:1)
我同意https://stackoverflow.com/users/811172/jon-garvin的分析,即您只运行一个服务器进程,但我会提到另一个解决方案。重构您的PDF生成,以便您不依赖于您的控制器。
如果你正在使用Prawnto,我猜你有一个像
这样的观点# app/views/response.pdf.prawn
pdf.text "Hello world"
将其移至Response
模型:(或其他更合适的地方,如演示者)
# app/models/response.rb
require 'tmpdir'
class Response < ActiveRecord::Base
def pdf_path
return @pdf_path if @pdf_generated == true
@pdf_path = File.join(Dir.tmpdir, rand(1e11).to_s)
Prawn::Document.generate(@pdf_path) do |pdf|
pdf.text "Hello world"
end
@pdf_generated = true
@pdf_path
end
def pdf_cleanup
if @pdf_generated and File.exist?(@pdf_path.to_s)
File.unlink @pdf_path
end
end
end
然后在ResponsesController
你可以做到:
# app/controllers/responses_controller.rb
def show
@response = Response.find params[:id]
respond_to do |format|
# this sends the PDF to the browser (doesn't email it)
format.pdf { send_file @response.pdf_path, :type => 'application/pdf', :disposition => 'attachment', :filename => 'test.pdf' }
end
end
在您的邮件中,您可以这样做:
# this sends an email with the PDF attached
def confirm_complete(response)
email_address = response.supervisor_id
attachments['test.pdf'] = {:mime_type => "application/pdf", :content => File.read(response.pdf_path, :binmode => true) }
mail to: email_address, subject: 'Thank you for your feedback!'
end
由于您是在tmpdir中创建的,因此在服务器重新启动时会自动删除它。您也可以调用清理功能。
最后一点注意事项:您可能希望使用其他型号名称,例如SupervisorReport
或某些内容 - Response
可能会让您在以后遇到名称空间问题