如何在 ruby​​ 中合并 PDF?

发布于 2024-09-14 19:18:06 字数 503 浏览 2 评论 0原文

这是2008 年提出的问题< /a>.希望现在有更好的答案。

如何在 ruby​​ 中合并 PDF?

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

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

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

This was asked in 2008. Hopefully there's a better answer now.

How can you combine PDFs in ruby?

I'm using the pdf-stamper gem to fill out a form in a PDF. I'd like to take n PDFs, fill out a form in each of them, and save the result as an n-page document.

Can you do this with a native library like prawn? Can you do this with rjb and iText? pdf-stamper is a wrapper on iText.

I'd like to avoid using two libraries (i.e. pdftk and iText), if possible.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

挖个坑埋了你 2024-09-21 19:18:06

从 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

As of 2013 you can use Prawn to merge pdfs. Gist: 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
旧伤慢歌 2024-09-21 19:18:06

经过长时间寻找纯 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")

如果您发现任何问题,请告诉我,我将致力于修复。

After a long search for a pure Ruby solution, I ended up writing code from scratch to parse and combine/merge PDF files.

(I feel it is such a mess with the current tools - I wanted something native but they all seem to have different issues and dependencies... even Prawn dropped the template support they use to have)

I posted the gem online and you can find it at GitHub as well.

you can install it with:

gem install combine_pdf

It's very easy to use (with or without saving the PDF data to a file).

For example, here is a "one-liner":

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

If you find any issues, please let me know and I will work on a fix.

回心转意 2024-09-21 19:18:06

使用 Ghostscript 合并 PDF:

 options = "-q -dNOPAUSE -dBATCH -sDEVICE=pdfwrite"
 system "gs #{options} -sOutputFile=result.pdf file1.pdf file2.pdf"

Use ghostscript to combine PDFs:

 options = "-q -dNOPAUSE -dBATCH -sDEVICE=pdfwrite"
 system "gs #{options} -sOutputFile=result.pdf file1.pdf file2.pdf"
醉城メ夜风 2024-09-21 19:18:06

我编写了一个 ruby​​ gem 来执行此操作 - PDF::Merger。它使用 iText。使用方法如下:

pdf = PDF::Merger.new
pdf.add_file "foo.pdf"
pdf.add_file "bar.pdf"
pdf.save_as "combined.pdf"

I wrote a ruby gem to do this — PDF::Merger. It uses iText. Here's how you use it:

pdf = PDF::Merger.new
pdf.add_file "foo.pdf"
pdf.add_file "bar.pdf"
pdf.save_as "combined.pdf"
白衬杉格子梦 2024-09-21 19:18:06

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

system "pdftk #{file_1} multistamp #{file_2} output #{file_combined}"

Haven't seen great options in Ruby- I got best results shelling out to pdftk:

system "pdftk #{file_1} multistamp #{file_2} output #{file_combined}"
孤檠 2024-09-21 19:18:06

我们比 2008 年更接近了,但还没有完全实现。

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

We're closer than we were in 2008, but not quite there yet.

The latest dev version of Prawn lets you use an existing PDF as a template, but not use a template over and over as you add more pages.

念﹏祤嫣 2024-09-21 19:18:06

通过 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();

Via iText, this will work... though you should flatten the forms before you merge them to avoid field name conflicts. That or rename the fields one page at a time.

Within PDF, fields with the same name share a value. This is usually not the desired behavior, though it comes in handy from time to time.

Something along the lines of (in 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();
↘人皮目录ツ 2024-09-21 19:18:06

如果您想使用 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"

If you want to add any template (created by macOS Pages or Google Docs) using the combine_pdf gem then you can try with this:

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"
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文