如何使用prawn gem将Base64字符串转换为pdf文件

9
我想从数据库记录中生成 pdf 文件,将其编码为 Base64 字符串并存储到数据库中。 这个过程是正常的。 现在我想进行相反的操作,如何解码 Base64 字符串并再次生成 pdf 文件?
以下是我目前尝试的方法。
def data_pdf_base64
  begin
    # Create Prawn Object
    my_pdf = Prawn::Document.new
    # write text to pdf
    my_pdf.text("Hello Gagan, How are you?")
    # Save at tmp folder as pdf file
    my_pdf.render_file("#{Rails.root}/tmp/pdf/gagan.pdf")
    # Read pdf file and encode to Base64
    encoded_string = Base64.encode64(File.open("#{Rails.root}/tmp/pdf/gagan.pdf"){|i| i.read})
    # Delete generated pdf file from tmp folder
    File.delete("#{Rails.root}/tmp/pdf/gagan.pdf") if File.exist?("#{Rails.root}/tmp/pdf/gagan.pdf")
    # Now converting Base64 to pdf again
    pdf = Prawn::Document.new
    # I have used ttf font because it was giving me below error
    # Your document includes text that's not compatible with the Windows-1252 character set. If you need full UTF-8 support, use TTF fonts instead of PDF's built-in fonts.
    pdf.font Rails.root.join("app/assets/fonts/fontawesome-webfont.ttf")
    pdf.text Base64.decode64 encoded_string
    pdf.render_file("#{Rails.root}/tmp/pdf/gagan2.pdf")
  rescue => e
    return render :text => "Error: #{e}"
  end
end

现在我遇到以下错误:
编码ASCII-8BIT无法透明地转换为UTF-8。请确保您尝试使用的字符串的编码已正确设置。
我尝试了如下方法如何在Rails中使用Prawn将Base64字符串转换为PNG而无需保存到服务器,但它给出了以下错误:
从ASCII-8BIT到UTF-8的"\xFF"。
有人能指出我漏掉了什么吗?

你的问题不够清晰。首先,你说你将一个PDF文件存储在数据库中。然后你又问如何从数据库中的数据生成PDF文件。但是你刚才说数据本身就是PDF文件!那么到底是哪个呢? - Jörg W Mittag
1
但是你已经生成了PDF文件!为什么要再次生成它,当你可以从数据库中检索它呢? - Jörg W Mittag
@JörgWMittag:是的,我已经生成了PDF文件并可以将其发送给用户,但出于安全原因,我不能将PDF文件存储到数据库中,而是存储编码字符串。现在,在某些方法中,我需要从存储的编码字符串生成PDF文件。 - Gagan Gami
但是,为什么您必须重新生成PDF?为什么不直接获取您在数据库中存储的PDF文件呢? - Jörg W Mittag
让我们在聊天中继续这个讨论 - Gagan Gami
显示剩余9条评论
1个回答

12
答案是解码Base64编码的字符串,然后直接发送或直接保存到磁盘(将其命名为PDF文件,但不使用prawn)。
解码后的字符串是PDF文件数据的二进制表示,因此无需使用Prawn或重新计算PDF数据的内容。
即。
 raw_pdf_str = Base64.decode64 encoded_string
 render :text, raw_pdf_str # <= this isn't the correct rendering pattern, but it's good enough as an example.

编辑

为了澄清评论中提供的一些信息:

  1. It's possible to send the string as an attachment without saving it to disk, either using render text: raw_pdf_str or the #send_data method (these are 4.x API versions, I don't remember the 5.x API style).

  2. It's possible to encode the string (from the Prawn object) without saving the rendered PDF data to a file (save it to a String object instead). i.e.:

    encoded_string = Base64.encode64(my_pdf.render)
    
  3. The String data could be used directly as an email attachment, similarly to the pattern provided here only using the String directly instead of reading any data from a file. i.e.:

    # inside a method in the Mailer class
    attachments['my_pdf.pdf'] = { :mime_type => 'application/pdf',
                                  :content => raw_pdf_str } 
    

谢谢您的回答,我可以将其作为附件发送而不保存为物理文件吗? - Gagan Gami
render 工作正常,我已将编码字符串转换为实际的 PDF 文件,但我不想将该文件保存在任何地方,而是希望得到一些文件对象,可以将其附加到邮件中,而无需将其保存到磁盘上作为临时文件。 - Gagan Gami
@GaganGami,我不确定我理解你的要求...就电子邮件附件而言,String对象是一个可以附加到电子邮件的对象(就像PDF文件一样),而无需将任何内容保存到磁盘。 - Myst
不用担心,兄弟,感谢你关于render的帮助,它对我很有帮助。我已经附上了文件,而没有将其保存为物理文件。参考链接:https://dev59.com/K2435IYBdhLWcg3w50j4 - Gagan Gami
将以下与编程有关的内容从英语翻译为中文。只返回翻译后的文本:我会发布我的完整答案,以便日后帮助任何其他人。 - Gagan Gami
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接