CombinePDF Documentation

repository·master·Indexed 21 days ago

https://github.com/boazsegev/combine_pdf

A pure Ruby library for parsing, merging, watermarking, and stamping PDF files. It provides functionality for combining multiple PDF documents, adding page numbering, creating tables, resizing pages, and overlaying content. The library supports loading PDFs from files or memory and rendering them back to files or strings.

Tokens
8.4K
Snippets
36
Records
37
Agent score
73%

What's inside CombinePDF

  1. Combine or merge PDF files and pages

    master

    You can merge multiple PDF files or specific pages into a single PDF object using the << operator.

    Note that adding an entire file via CombinePDF.load is faster than adding pages one by one.

    To merge files:

    pdf = CombinePDF.new
    pdf << CombinePDF.load("file1.pdf")
    pdf << CombinePDF.load("file2.pdf")
    pdf.save "combined.pdf"

    To merge specific pages (e.g., only even pages):

    pdf = CombinePDF.new
    i = 0
    CombinePDF.load("file.pdf").pages.each do |page|
      i += 1
      pdf << page if i.even?
    end
    pdf.save "even_pages.pdf"
  2. Render PDF data to files or memory

    master

    You can output the PDF content as a string (useful for web responses) or save it directly to a file.

    To a string (Memory)

    Use .to_pdf to get the raw PDF data string.

    In a Rails controller:

    send_data combined_file.to_pdf, filename: "combined.pdf", type: "application/pdf"

    In Sinatra:

    status 200
    body combined_file.to_pdf
    headers 'content-type' => "application/pdf"

    To a file

    Use the .save method:

    combined_file.save "output.pdf"
  3. Load and parse PDF data from files or memory

    master

    CombinePDF can load data from the file system or parse raw PDF data directly from memory (useful for data received via HTTP or generated by other libraries like Prawn).

    From a file

    pdf = CombinePDF.load("file.pdf")

    From memory (String)

    pdf = CombinePDF.parse(pdf_data)

    Example: Loading from a URL

    require 'combine_pdf'
    require 'net/http'
    
    url = "https://example.com/my.pdf"
    pdf = CombinePDF.parse Net::HTTP.get_response(URI.parse(url)).body
  4. Configure page numbering with `number_pages`

    master

    The number_pages method allows you to add page numbers with various formatting, locations, and styles.

    Basic usage:

    pdf = CombinePDF.load "file_to_number.pdf"
    pdf.number_pages
    pdf.save "file_with_numbering.pdf"

    Configuration Options

    • location: An array of locations (e.g., [:bottom_right], [:top, :bottom, :top_left, :top_right, :bottom_left, :bottom_right]).
    • number_format: A string for formatting (e.g., " %s ").
    • start_at: The starting value or character (e.g., 4 or "a").
    • page_range: A range of pages to number (e.g., (0..2) or (3..-1)).
    • box_color: RGB array for the box color.
    • border_color: RGB array for the border color.
    • border_width: Integer width of the border.
    • box_radius: Integer radius for rounded corners.
    • opacity: Float value for transparency.
    • font_size: Integer for font size.

    Example: Complex Numbering

    To number the first 3 pages with letters (a, b, c) and the rest with numbers (4, 5, ...) with a semi-transparent box:

    # Number first 3 pages as "a", "b", "c"
    pdf.number_pages(number_format: " %s ",
                     location: [:top, :bottom, :top_left, :top_right, :bottom_left, :bottom_right],
                     start_at: "a",
                     page_range: (0..2),
                     box_color: [0.8,0.8,0.8],
                     border_color: [0.4, 0.4, 0.4],
                     border_width: 1,
                     box_radius: 6,
                     opacity: 0.75)
    
    # Number the rest of the pages as 4, 5, ... etc
    pdf.number_pages(number_format: " %s ",
                     location: [:top, :bottom, :top_left, :top_right, :bottom_left, :bottom_right],
                     start_at: 4,
                     page_range: (3..-1),
                     box_color: [0.8,0.8,0.8],
                     border_color: [0.4, 0.4, 0.4],
                     border_width: 1,
                     box_radius: 6,
                     opacity: 0.75)
    pdf.number_pages(number_format: " %s ", location: :bottom_right, font_size: 44)
  5. Add content to existing pages (Stamp or Watermark)

    master

    To add content (like a logo or watermark) to existing pages, you must first load the content from a PDF file. You then use the << operator on individual pages (not the PDF object) to overlay the content.

    Important: The << operator behaves differently on PDF objects versus Pages. On a Page, it performs an overlay.

    To overlay a logo on every page:

    company_logo = CombinePDF.load("company_logo.pdf").pages[0]
    pdf = CombinePDF.load("content_file.pdf")
    pdf.pages.each {|page| page << company_logo}
    pdf.save "content_with_logo.pdf"

    For overlaying pages using compressed data that might not be editable, you can use the non-secure injection method:

    pdf.pages(nil, false).each {|page| page << stamp_page}
    company_logo = CombinePDF.load("company_logo.pdf").pages[0]
    pdf = CombinePDF.load "content_file.pdf"
    pdf.pages.each {|page| page << company_logo}
    pdf.save "content_with_logo.pdf"
  6. How to safely copy a PDF page

    master

    When 'stamping' one PDF page over another, font or resource conflicts can occur. To prevent this, use the copy(true) method. Passing true (the secure flag) ensures that resource identifiers (like fonts) are renamed to guarantee uniqueness in the new context.

    Note: The older make_secure and make_unsecure methods are deprecated. Use copy(true) instead.

    # Safe way to prepare a page for stamping/overlaying
    safe_page = other_page.copy(true)
    page << safe_page
  7. Combine and merge PDF files or pages

    master

    You can merge multiple PDF files or specific pages into a single PDF object using the << (append) or >> (prepend) operators. Adding whole files is faster than adding pages one by one.

    Append to end

    pdf = CombinePDF.new
    pdf << CombinePDF.load("file1.pdf")
    pdf << CombinePDF.load("file2.pdf")
    pdf.save "combined.pdf"

    Prepend to beginning

    pdf = CombinePDF.new "second_file.pdf"
    pdf >> CombinePDF.new "first_file.pdf"
    pdf.save "both_files_merged.pdf"

    One-liner approach

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

    Selective page merging

    To merge only specific pages (e.g., even pages), iterate through the pages of a loaded file:

    pdf = CombinePDF.new
    i = 0
    CombinePDF.load("file.pdf").pages.each do |page|
      i += 1
      pdf << page if i.even?
    end
    pdf.save "even_pages.pdf"
    pdf = CombinePDF.new
    pdf << CombinePDF.load("file1.pdf")
    pdf << CombinePDF.load("file2.pdf")
    pdf.save "combined.pdf"
  8. Add content to existing pages (Stamp / Watermark)

    master

    You can overlay content (like a logo or text) onto existing PDF pages. To do this, import the content from another PDF and use the << operator on individual Page objects.

    Note: The << operator behaves differently on PDF objects (merging files) versus Page objects (overlaying content).

    company_logo = CombinePDF.load("company_logo.pdf").pages[0]
    pdf = CombinePDF.load "content_file.pdf"
    pdf.pages.each {|page| page << company_logo}
    pdf.save "content_with_logo.pdf"

    Using stamp_pages for overlays

    If the stamp is a PDF page, you can use stamp_pages. Use the :underlay option to place the stamp behind the existing content:

    # Overlay (default)
    pdf.stamp_pages(stamp_page)
    
    # Underlay (reverse-stamp)
    pdf.stamp_pages(stamp_page, underlay: true)
    company_logo = CombinePDF.load("company_logo.pdf").pages[0]
    pdf = CombinePDF.load "content_file.pdf"
    pdf.pages.each {|page| page << company_logo}
    pdf.save "content_with_logo.pdf"
  9. Set a font for a PDF page

    master

    Use set_font to create a font object and add it to the page's resources dictionary. This returns the name of the font to be used in the content stream.

    Supported font symbols include:

    • :Helvetica (and variants like `:
  10. Handle encrypted or optional content PDFs

    master

    CombinePDF has specific behaviors for certain types of PDF files:

    Encrypted PDFs

    Encrypted files may fail quietly. To force a loud failure, use the raise_on_encrypted: true option:

    CombinePDF.load(pdf_file, raise_on_encrypted: true)

    This will raise a CombinePDF::EncryptionError.

    Optional Content PDFs

    If a PDF contains optional content sections, CombinePDF might raise an exception. You can bypass this by passing allow_optional_content: true to load or parse:

    CombinePDF.load(pdf_file, allow_optional_content: true)