如何使用Ruby编辑或编写现有的PDF?

44

我有一些带有复杂内容和几个空白区域的PDF模板文件。我需要能够在这些空白区域编写文本,并将生成的PDF保存在文件夹中。

我非常努力地在谷歌上搜索了此问题的答案,但没有找到明确的答案。其中一个更好的解决方案是PDF::Toolkit,但它需要购买Adobe Acrobat才能向现有PDF文档添加可替换属性。

PHP世界得到了FPDI的祝福,可以简单地打开PDF文件并在现有内容上编写/绘制。有该库的Ruby端口,但最后一次提交是在2009年初。而且那个项目似乎没有得到广泛使用和支持。

问题是:有什么更好的Ruby方法可以编辑、编写或绘制现有的PDF吗?

这个问题在这里也没有被回答。这些问题是相关的,但不是完全相同的:

8个回答

35

你一定需要了解 Prawn gem,它可以生成任何自定义的PDF文件。你可以使用prawn将文本写入现有的PDF中,并将现有的PDF视为新Prawn文档的模板。

例如:

filename = "#{Prawn::DATADIR}/pdfs/multipage_template.pdf"
Prawn::Document.generate("full_template.pdf", :template => filename) do
  text "THis content is written on the first page of the template", :align => :center
end
这将在旧pdf的第一页上写入文本。
更多信息请参见: http://prawn.majesticseacreature.com/manual.pdf

是的,我已经考虑过了(甚至在我的问题中列出了),但编辑现有的PDF是我的项目要求。谢谢你的回答。 - Alex Kovshovik
我有这个问题,你有什么想法吗?https://dev59.com/z2fWa4cB1Zd3GeqPiJHe - Sebastien
3
我使用这种方法来大量添加文本到现有的PDF中。为什么这个答案对你不起作用? - Matt Schwartz
11
支持模板的功能在Prawn 0.13.0中被删除,在0.14.0中默认禁用,并在0.15.0中被提取出来。- 来自https://github.com/prawnpdf/prawn-templates - Michael Reinsch
6
在Prawn中,模板支持被弃用了(正如@MichaelReinsch的帖子所详述的那样),因此我最终编写了一个Ruby实现来组合PDF文件、加盖印章、按顺序合并它们以及叠放在彼此之上、添加简单文本、提取PDF字体和其他简单任务。这个gem后来在Paweł Gościcki的回答中被提到了:combine_pdf - Myst

25

因为Prawn已经移除了模板功能(它存在很多的bug),我找到的最简单的方法如下:

  1. 使用Prawn只生成包含您想添加的动态部分的PDF。
  2. 使用PDF::Toolkit(这个工具包装了PDFtk)将Prawn PDF与原始PDF合并。

简单示例:

require 'prawn'
require 'pdf/toolkit'

template_filename = 'some/dir/Awesome-Graphics.pdf'
prawn_filename = 'temp.pdf'
output_filename = 'output.pdf'

Prawn::Document.generate(prawn_filename) do
  # Generate whatever you want here.
  text_box "This is some new text!", :at => [100, 300]
end

PDF::Toolkit.pdftk(prawn_filename, "background", template_filename, "output", output_filename)

23

我建议使用prawn生成PDF,然后使用combine_pdf将两个生成的PDF组合成一个。 我像这样使用它,它完全可以正常工作。

以下是如何组合两个PDF的简短示例(摘自README):

company_logo = CombinePDF.load("company_logo.pdf").pages[0]
pdf = CombinePDF.load "content_file.pdf"
pdf.pages.each { |page| page << company_logo } # notice the << operator is on a page and not a PDF object.
pdf.save "content_with_logo.pdf"

1
我发现这对我不起作用,因为“logo”文件(对我来说,它是一个总体模板,我只是添加了一点文本)会覆盖我所添加的任何内容(使用Prawn::PDF,类似于其他一些答案)。我发现这个解决方案适合我(替换此答案中第3行块内部的内容):page.replace(company_logo.copy << page) - lindes
2
这对我有用,我认为这是比PDF::Toolkit路线更清晰的解决方案,而且对我也行不通。 - Jason Swett

17

你不需要使用多个 gem,只需使用一个 gem 即可!

在 Ruby/Rails 中处理 PDF 真的很具有挑战性(我已经发现了!)

以下是我能够在 Rails 中动态添加文本到 PDF 的方法。

将此 gem 添加到您的 gem 文件中:combine_pdf

然后您可以使用类似于以下代码:

# get the record from the database to add dynamically to the pdf
user = User.last

# get the existing pdf
pdf = CombinePDF.load "#{Rails.root}/public/pdf/existing_pdf.pdf"

# create a textbox and add it to the existing pdf on page 2
pdf.pages[1].textbox "#{user.first_name} #{user.last_name}", height: 20, width: 70, y: 596, x: 72

# output the new pdf which now contains your dynamic data
pdf.save "#{Rails.root}/public/pdf/output#{Time.now.to_s}.pdf"

您可以在这里找到有关textbox方法的详细信息: https://www.rubydoc.info/gems/combine_pdf/0.2.5/CombinePDF/Page_Methods#textbox-instance_method

我花了几天时间通过许多不同的gem(prawnwicked_pdfpdfkitfillable_pdf)来解决问题。

但是,截至2019年,这对我来说是最顺畅的解决方案。

我希望这能节省其他人很多时间,这样他们就不必像我一样经历所有的PDF试错!!


哇 :) 我不知道为什么这个答案的点赞数很低..这应该在最顶部..你提供了完整的工作代码和优雅的解决方案.. - Code Tree
1
@CodeTree 谢谢,很高兴它为你节省了我所经历的所有痛苦!随意点赞,这样可以帮助更多的人! - Sami Birnbaum

1
我能想到的最好的选择是Rails-latex,它不能让你编辑现有的PDF文件,但是可以设置模板*.tex.erb文件,您可以动态修改并将其编译成PDF格式(以及其他几种格式)。

谢谢您的回答,但在我的情况下,编辑现有的PDF是必需的。对于创建新的PDF,像prawn这样的东西对我来说可能会起作用... - Alex Kovshovik

1

PDFLib 似乎可以实现你想要的功能,并且有 Ruby 绑定。


这确实看起来是一个很棒的工具,但由于它不是开源的(不免费)- 我们必须考虑价格。我们可以使用的版本大约是2100美元 - 这对于我们低预算的小项目来说是很多的。而且这可能不能被认为是“Rails-way”,因为它太贵了 :)我可能会继续使用PDF::Toolkit,并使用它来填充PDF属性值,而不是在PDF上进行绘制。但是非常感谢您的回答 - 我真的很感激! - Alex Kovshovik
是的,在一开始就承担如此巨大的成本总是很困难的。前段时间购买了Prince XML用于生成PDF文件,当时看起来花费很高,但现在看来它是物有所值的。 - Joel Meador
我在我的另一个项目中也使用Prince XML - 它可以工作,但不幸的是对于我正在尝试解决的这个问题不适用。 - Alex Kovshovik
值得注意的是,版本“n-1” - v7 - 提供免费的源代码http://www.pdflib.com/en/download/free-software/pdflib-lite-7/,但不受支持。我也不知道“lite”削减了多少功能。 - quetzalcoatl

0

您可以使用Origami gem为现有的PDF文件添加密码或进行编辑。

pdf = WickedPdf.new.pdf_from_url(pdf_params[:url])
temp_file = Tempfile.new('temp', encoding: 'ascii-8bit')
temp_file.write(pdf)

# Creates an encrypted document with AES256 and passwords.
pdf = PDF.read(temp_file.path).encrypt(cipher: 'aes', key_size: 256,user_passwd: pdf_params[:user_password], owner_passwd: pdf_params[:owner_password])
save_path = "#{File.basename(__FILE__, ".rb")}.pdf"

pdf.save(save_path)
temp_file.close

0
根据我的研究,Prawn是我发现的免费和最好的宝石之一。模板功能在后来的版本中不起作用。我能找到的最新版本与模板配合使用的是1.0.0.rc2 - 2013年3月1日。找不到任何后续版本可以与模板配合使用。因此,如果您使用比这个版本更高的版本,请注意。请查看下面的主题以获取更多信息。

https://groups.google.com/forum/#!searchin/prawn-ruby/prawn$20templates/prawn-ruby/RYGPImNcR0I/7mxtnrEDHeQJ

PDFtk是另一个处理PDF和模板的强大工具。但它提到了以下几点:

  • 此库可供个人免费使用,但如果用于生产则需要许可证
  • 这是一个非Ruby命令行工具

有关更多信息,请参阅下面的链接 http://adamalbrecht.com/2014/01/31/pre-filling-pdf-form-templates-in-ruby-on-rails-with-pdftk/


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