How do you combine PDFs in ruby?

此生再无相见时 提交于 2019-11-30 02:26:58

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

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.

Use ghostscript to combine PDFs:

 options = "-q -dNOPAUSE -dBATCH -sDEVICE=pdfwrite"
 system "gs #{options} -sOutputFile=result.pdf file1.pdf file2.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"

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}"

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.

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

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"
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!