如何处理file_as_string(由Prawn生成)以便Carrierwave接受它?

我正在使用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 )似乎应该可以工作,但我不清楚它为什么会产生这个错误。

事实certificate, 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 
Interesting Posts