我正在使用Prawn从Rails应用程序的控制器生成PDF,
...
respond_to do |format|
format.pdf do
pdf = GenerateReportPdf.new(@object, view_context)
send_data pdf.render, filename: "Report", type: "application/pdf", disposition: "inline"
end
end
这很好用,但我现在想将GenerateReportPdf移动到后台任务中,并将生成的对象传递给Carrierwave直接上传到S3。
工人看起来像这样
def perform
pdf = GenerateReportPdf.new(@object)
fileString = ???????
document = Document.new(
object_id: @object.id,
file: fileString )
# file is field used by Carrierwave
end
如何处理Prawn返回的对象(?????
)确保它是Carrierwave可以读取的格式。
fileString = pdf.render_file 'filename'
将对象写入应用程序的根目录。因为我在Heroku上这是不可能的。
file = pdf.render
回报 ArgumentError: string contains null byte
fileString = StringIO.new( pdf.render_file 'filename' )
回报 TypeError: no implicit conversion of nil into String
fileString = StringIO.new( pdf.render )
回报 ActiveRecord::RecordInvalid: Validation failed: File You are not allowed to upload nil files, allowed types: jpg, jpeg, gif, png, pdf, doc, docx, xls, xlsx
fileString = File.open( pdf.render )
回报 ArgumentError: string contains null byte
....等等。
我错过了什么? StringIO.new( pdf.render )
好像它应该工作,但我不清楚为什么它产生这个错误。
事实证明 StringIO.new( pdf.render )
应该确实有效。
我遇到的问题是文件名设置不正确,尽管遵循Carrierwave的wiki下面的建议,代码中其他地方的错误意味着文件名作为空字符串返回。我忽略了这个假设需要别的东西
https://github.com/carrierwaveuploader/carrierwave/wiki/How-to:-Upload-from-a-string-in-Rails-3
我的代码最终看起来像这样
def perform
s = StringIO.new(pdf.render)
def s.original_filename; "my file name"; end
document = Document.new(
object_id: @object.id
)
document.file = s
document.save!
end
事实证明 StringIO.new( pdf.render )
应该确实有效。
我遇到的问题是文件名设置不正确,尽管遵循Carrierwave的wiki下面的建议,代码中其他地方的错误意味着文件名作为空字符串返回。我忽略了这个假设需要别的东西
https://github.com/carrierwaveuploader/carrierwave/wiki/How-to:-Upload-from-a-string-in-Rails-3
我的代码最终看起来像这样
def perform
s = StringIO.new(pdf.render)
def s.original_filename; "my file name"; end
document = Document.new(
object_id: @object.id
)
document.file = s
document.save!
end
你想要创建一个临时文件(只要你不希望它在请求中持续存在,就可以在Heroku上运行)。
def perform
# Create instance of your Carrierwave Uploader
uploader = MyUploader.new
# Generate your PDF
pdf = GenerateReportPdf.new(@object)
# Create a tempfile
tmpfile = Tempfile.new("my_filename")
# set to binary mode to avoid UTF-8 conversion errors
tmpfile.binmode
# Use render to write the file contents
tmpfile.write pdf.render
# Upload the tempfile with your Carrierwave uploader
uploader.store! tmpfile
# Close the tempfile and delete it
tmpfile.close
tmpfile.unlink
end
这里有一种方法可以像Andy Harvey一样使用StringIO,但是没有向StringIO intstance的本征类添加方法。
class VirtualFile < StringIO
attr_accessor :original_filename
def initialize(string, original_filename)
@original_filename = original_filename
super(string)
end
end
def perform
pdf_string = GenerateReportPdf.new(@object)
file = VirtualFile.new(pdf_string, 'filename.pdf')
document = Document.new(object_id: @object.id, file: file)
end