sgr-ksmt / PDFGenerator

A simple generator of PDF written in Swift.
MIT License
757 stars 110 forks source link

Add PDF page to existing PDF #83

Open Patrice89 opened 7 years ago

Patrice89 commented 7 years ago

Hey guys,

I'm currently working on a project where I don't want to store one PDF at the end of a session but append everytime one page. As I see it at the moment, it would be good to have a function to add pages with the generator.

Cheers,

yarodevuci commented 6 years ago

@sgr-ksmt any updates on that @Patrice89 ?

mihailsalari commented 5 years ago

Use this method:

   /**
   Append image.

   - parameter pdfURL: Original PDF url.
   - parameter image: An image.
   - throws: A thrown if some error occurred.
   - finishCompletion: completion when all process are finished
   */
  class func insertPage(in pdfURL: URL,
                        image: UIImage, finishCompletion: () -> Void) throws {
    // Temp Documents dir
    let tempDirectoryPath = NSTemporaryDirectory()

    // File paths
    let pdfPath1 = pdfURL
    let pdfPath2 = URL(fileURLWithPath: tempDirectoryPath).appendingPathComponent("temporary_pdf_2.pdf")

    let pdfData = try PDFGenerator.generated(by: image)
    try pdfData.write(to: pdfPath2)
    let pdfPathOutput = URL(fileURLWithPath: tempDirectoryPath).appendingPathComponent("pdf_output.pdf")

    // File references
    guard let pdfRef1 = CGPDFDocument(pdfPath1 as CFURL) else {
      throw PDFGenerateError.imageLoadFailed(pdfPath1)
    }

    guard let pdfRef2 = CGPDFDocument(pdfPath2 as CFURL) else {
      throw PDFGenerateError.imageLoadFailed(pdfPath2)
    }

    // Create the output context
    let writeContext = CGContext(pdfPathOutput as CFURL, mediaBox: nil, nil)

    func interate(in document: CGPDFDocument, context: CGContext?) throws {
      // Loop variables
      var page: CGPDFPage?
      var mediaBox: CGRect

      // Read the first PDF and generate the output pages
      for i in 1...document.numberOfPages {
        page = document.page(at: i)

        if let page = page {
          mediaBox = page.getBoxRect(CGPDFBox.mediaBox)
          context?.beginPage(mediaBox: &mediaBox)
          context?.drawPDFPage(page)
          context?.endPage()
        } else {
          throw PDFGenerateError.emptyPage
        }
      }
    }

    try interate(in: pdfRef1, context: writeContext)
    try interate(in: pdfRef2, context: writeContext)

    // Finalize the output file
    writeContext?.closePDF()

    let data = try Data(contentsOf: pdfPathOutput)
    try FileManager.default.removeItem(at: pdfURL)
    try data.write(to: pdfURL)

    finishCompletion()
  }