16

这是2008 年提出的。希望现在有更好的答案。

如何在 ruby​​ 中合并 PDF?

我正在使用pdf-stamper gem在 PDF 中填写表格。我想获取n 个PDF,在每个 PDF 中填写一个表格,然后将结果保存为n页文档。

你能用像虾这样的原生库来做到这一点吗?你能用 rjb 和 iText 做到这一点吗?pdf-stamper 是 iText 的包装器。

如果可能的话,我想避免使用两个库(即 pdftk 和 iText)。

4

8 回答 8

20

自 2013 年起,您可以使用 Prawn 合并 pdf。要点:https ://gist.github.com/4512859

class PdfMerger

  def merge(pdf_paths, destination)

    first_pdf_path = pdf_paths.delete_at(0)

    Prawn::Document.generate(destination, :template => first_pdf_path) do |pdf|

      pdf_paths.each do |pdf_path|
        pdf.go_to_page(pdf.page_count)

        template_page_count = count_pdf_pages(pdf_path)
        (1..template_page_count).each do |template_page_number|
          pdf.start_new_page(:template => pdf_path, :template_page => template_page_number)
        end
      end

    end

  end

  private

  def count_pdf_pages(pdf_file_path)
    pdf = Prawn::Document.new(:template => pdf_file_path)
    pdf.page_count
  end

end
于 2013-01-11T18:59:13.313 回答
18

经过长时间寻找纯 Ruby 解决方案后,我最终从头开始编写代码来解析和合并/合并 PDF 文件。

(我觉得当前的工具太乱了——我想要一些原生的东西,但它们似乎都有不同的问题和依赖关系......甚至 Prawn 也放弃了他们曾经拥有的模板支持)

我在网上发布了 gem ,你也可以在GitHub 上找到它。

你可以安装它:

gem install combine_pdf

它非常易于使用(无论是否将 PDF 数据保存到文件中)。

例如,这是一个“单线”:

(CombinePDF.load("file1.pdf") << CombinePDF.load("file2.pdf") << CombinePDF.load("file3.pdf")).save("out.pdf")

如果您发现任何问题,请告诉我,我会努力解决。

于 2014-09-10T02:50:59.400 回答
11

使用 ghostscript 组合 PDF:

 options = "-q -dNOPAUSE -dBATCH -sDEVICE=pdfwrite"
 system "gs #{options} -sOutputFile=result.pdf file1.pdf file2.pdf"
于 2012-01-19T15:22:00.833 回答
5

为此,我编写了一个 ruby​​ gem —— PDF::Merger。它使用 iText。以下是你如何使用它:

pdf = PDF::Merger.new
pdf.add_file "foo.pdf"
pdf.add_file "bar.pdf"
pdf.save_as "combined.pdf"
于 2010-10-20T17:31:40.923 回答
2

在 Ruby 中还没有看到很好的选择——我在pdftk中得到了最好的结果:

system "pdftk #{file_1} multistamp #{file_2} output #{file_combined}"
于 2014-01-11T17:02:21.800 回答
0

我们比 2008 年更接近,但还没有完全达到。

最新的 Prawn 开发版允许您使用现有的 PDF 作为模板,但不能在添加更多页面时一遍又一遍地使用模板。

于 2010-08-17T08:28:14.057 回答
0

通过 iText,这将起作用......尽管您应该在合并表单之前将它们展平以避免字段名称冲突。或者一次重命名一页字段。

在 PDF 中,具有相同名称的字段共享一个值。这通常不是所需的行为,尽管它有时会派上用场。

类似于(在java中)的东西:

PdfCopy mergedPDF = new PdfCopy( new Document(), new FileOutputStream( outPath );

for (String path : paths ) {
  PdfReader reader = new PdfReader( path );
  ByteArrayOutputStream curFormOut = new ByteArrayOutputStream();
  PdfStamper stamper = new PdfStamper( reader, curFormOut );

  stamper.setField( name, value ); // ad nauseum

  stamper.setFlattening(true); // flattening setting only takes effect during close()
  stamper.close();

  byte curFormBytes = curFormOut.toByteArray();
  PdfReader combineMe = new PdfReader( curFormBytes );

  int pages = combineMe .getNumberOfPages();
  for (int i = 1; i <= pages; ++i) { // "1" is the first page
    mergedForms.addPage( mergedForms.getImportedPage( combineMe, i );
  }
}

mergedForms.close();
于 2010-10-18T22:57:18.117 回答
0

如果您想使用combine_pdf gem添加任何模板(由 macOS Pages 或 Google Docs 创建),那么您可以尝试以下操作:

final_pdf = CombinePDF.new
company_template = CombinePDF.load(template_file.pdf).pages[0]
pdf = CombinePDF.load (content_file.pdf)
pdf.pages.each {|page| final_pdf << (company_template << page)} 
final_pdf.save "final_document.pdf"
于 2018-09-11T11:51:40.653 回答