如何在ruby中合并PDFs ?

时间:2021-10-06 07:16:53

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

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

How can you combine PDFs in ruby?

如何在ruby中合并PDFs ?

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.

我正在用PDF格式的PDF格式填写表格。我想取n个PDFs,分别填写一个表单,并将结果保存为一个n页的文档。

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.

你能用对虾这样的本地库做这个吗?你能用rjb和iText做这个吗?pdf-stamper是iText上的包装器。

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

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

7 个解决方案

#1


20  

As of 2013 you can use Prawn to merge pdfs. Gist: https://gist.github.com/4512859

到2013年,你可以用虾合并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

#2


12  

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

在对纯Ruby解决方案进行了长时间的搜索之后,我最终从头开始编写代码来解析和合并PDF文件。

(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.

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

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).

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

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.

如果你发现任何问题,请告诉我,我会解决的。

#3


11  

Use ghostscript to combine PDFs:

使用ghostscript合并PDFs:

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

#4


5  

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

我写了一个ruby gem来做这个- PDF:: merge。它使用iText。以下是你如何使用它:

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

#5


2  

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

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

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

#6


0  

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

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

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.

最新的开发版本的对虾允许您使用现有的PDF作为模板,但是在您添加更多的页面时,不需要反复使用模板。

#7


0  

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.

通过iText,这将有效……尽管您应该在合并表单之前将它们压平,以避免字段名冲突。或者一次将字段重命名为一页。

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.

在PDF中,具有相同名称的字段共享一个值。这通常不是我们想要的行为,尽管它偶尔会派上用场。

Something along the lines of (in java):

(在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();

#1


20  

As of 2013 you can use Prawn to merge pdfs. Gist: https://gist.github.com/4512859

到2013年,你可以用虾合并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

#2


12  

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

在对纯Ruby解决方案进行了长时间的搜索之后,我最终从头开始编写代码来解析和合并PDF文件。

(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.

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

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).

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

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.

如果你发现任何问题,请告诉我,我会解决的。

#3


11  

Use ghostscript to combine PDFs:

使用ghostscript合并PDFs:

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

#4


5  

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

我写了一个ruby gem来做这个- PDF:: merge。它使用iText。以下是你如何使用它:

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

#5


2  

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

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

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

#6


0  

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

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

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.

最新的开发版本的对虾允许您使用现有的PDF作为模板,但是在您添加更多的页面时,不需要反复使用模板。

#7


0  

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.

通过iText,这将有效……尽管您应该在合并表单之前将它们压平,以避免字段名冲突。或者一次将字段重命名为一页。

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.

在PDF中,具有相同名称的字段共享一个值。这通常不是我们想要的行为,尽管它偶尔会派上用场。

Something along the lines of (in java):

(在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();