0
votes

I’m having a problem to concatenate PDFs. I have to concatenate 2 pdf files. Let us call the first pdf file “pdf1” and the second “pdf2” It will always have one page. And in order to concatenate them I made use of the function bellow, but the function bellow in order to concatenate pdf1 and pdf2 creates a new pdf file (let us call it pdf3) and keep adding all the pages from pdf1 and pdf2 on pdf3. What I would like to know, is there a way I can concatenate pdf2 on pdf1 without creating pdf3.

-(void) concatenaPDF:(NSNumber*)paginaSendoBaixada{

    NSString *cacheDir = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];

    // File paths
    cacheDir = [cacheDir stringByAppendingPathComponent:@"PDFs"];

    NSString *pdfPathOutput = [cacheDir stringByAppendingPathComponent:@"out.pdf"];

    // File URLs - bridge casting for ARC
    NSURL *pdfURL1 = [[NSURL alloc] initFileURLWithPath:self.filePath];
    NSURL *pdfURL2 = [[NSURL alloc] initFileURLWithPath:self.filePathPagina];
    CFURLRef pdfURLOutput =(__bridge_retained CFURLRef) [[NSURL alloc] initFileURLWithPath:(NSString *)pdfPathOutput];//(CFURLRef)

    // File references
    CGPDFDocumentRef pdfRef1 = CGPDFDocumentCreateWithURL((CFURLRef) pdfURL1);
    CGPDFDocumentRef pdfRef2 = CGPDFDocumentCreateWithURL((CFURLRef) pdfURL2);

    // Number of pages
    NSInteger numberOfPages1 = CGPDFDocumentGetNumberOfPages(pdfRef1);
    NSInteger numberOfPages2 = CGPDFDocumentGetNumberOfPages(pdfRef2);

    //se pagina do pdfbaxado for 0 e pq deu erro na baixa e vou ter que baixar denovo.
    if (numberOfPages2 == 0) {
        self.modeloParaItemSendoBaixado.model.paginaBaixando--;
        //vou apagar o pdf da pagina
        [self deleteFileAtPath:self.filePathPagina];
        return;    
    }

    if (numberOfPages1 > [paginaSendoBaixada integerValue]) {
        [self clearState];
        dispatch_async(dispatch_get_main_queue(), ^{
            UIAlertView* alertView = [[UIAlertView alloc] initWithTitle:@"Erro"
                                                            message:@"Falha na conexão.\nNão foi possível baixar a edição!"
                                                           delegate:nil
                                                  cancelButtonTitle:@"OK" otherButtonTitles:nil];
            [alertView show];
        });

    }

    // Create the output context
    CGContextRef writeContext = CGPDFContextCreateWithURL(pdfURLOutput, NULL, NULL);

    // Loop variables
    CGPDFPageRef page;
    CGRect mediaBox;

    // Read the first PDF and generate the output pages
    NSLog(@"GENERATING PAGES FROM PDF 1 (%li)...", (long)numberOfPages1);
    for (int i=1; i<=numberOfPages1; i++) {
        page = CGPDFDocumentGetPage(pdfRef1, i);
        mediaBox = CGPDFPageGetBoxRect(page, kCGPDFMediaBox);
        CGContextBeginPage(writeContext, &mediaBox);
        CGContextDrawPDFPage(writeContext, page);
        CGContextEndPage(writeContext);
    }

    // Read the second PDF and generate the output pages
    NSLog(@"GENERATING PAGES FROM PDF 2 (%li)...", (long)numberOfPages2);
    for (int i=1; i<=numberOfPages2; i++) {
        page = CGPDFDocumentGetPage(pdfRef2, i);
        mediaBox = CGPDFPageGetBoxRect(page, kCGPDFMediaBox);
        CGContextBeginPage(writeContext, &mediaBox);
        CGContextDrawPDFPage(writeContext, page);
        CGContextEndPage(writeContext);
    }
    NSLog(@"DONE!");

    // Finalize the output file
    CGPDFContextClose(writeContext);

    // Release from memory
    CGPDFDocumentRelease(pdfRef1);
    CGPDFDocumentRelease(pdfRef2);
    CGContextRelease(writeContext);


    [self deleteFileAtPathWithoutImage:self.filePath];


    NSFileManager *fileMan = [NSFileManager defaultManager];
    NSError *error = nil;
    if (self.filePath != nil) {
        if (![fileMan moveItemAtPath:pdfPathOutput toPath:self.filePath error:&error])
        {
            [self clearState];
            dispatch_async(dispatch_get_main_queue(), ^{
                UIAlertView* alertView = [[UIAlertView alloc] initWithTitle:@"Erro"
                                                                message:@"Falha na conexão.\nNão foi possível baixar a edição!"
                                                               delegate:nil
                                                      cancelButtonTitle:@"OK" otherButtonTitles:nil];
            [alertView show];
            });
            NSLog(@"Failed to move '%@' to '%@': %@", pdfPathOutput, self.filePath, [error localizedDescription]);
        }
    }  
}
1

1 Answers

0
votes

I don't think you're going to be able to generate a new instance of PDF1 without fully closing and releasing the original input copy first, so that the OS can overwrite the old PDF1 with a new output file of the same name. It's more direct to write out the newly merged output as PDF3, because the combined objects of PDF1 and PDF2 must be indexed and renumbered relative to each other.

That is, simply moving the content of PDF2 into PDF1 isn't going to work because you'll have two Object 1s, two Object 2s and so on. Thus the process is going to create your new PDF3 as a new destination, and will comprise both your input first Objects under new numbers (or combine their dictionaries, or whatever), plus the second Objects from each input, the third, and so on.

(I'm oversimplifying here a lot, as the sequence of objects in PDF1 and PDF2 is not going to match, but essentially the merging needs to combine the content of both, and then re-sort and re-index them; it's not a matter of just appending the second to the first and then closing it out.)

If your issue is specifically that you want the output to inherit the name of your first input file, I would suggest letting the process complete with a new PDF3 first, and then, after verifying a successful completion, you could delete your old PDF1 and then rename PDF3 in its place.

Note that if you really want to make the output of your process carry the name of one of your original input files, then you need to ensure that your process was successful, or you may end up with a bad output file and no surviving instance of your input file with which to try again.