Ben Szefler
Ben Szefler

Reputation: 102

Save PDF with password iOS

I am building an app that downloads PDF files from a server, adds a password and then saves the file locally.

I am struggling to add set a password for the file. Below is the function I run to set a password and save the file.

- (void)addPassword:(NSString *)password forPDFAtPath:(NSString *)path {
NSData *data = [NSData dataWithContentsOfFile:path];

//Create the pdf document reference
CGDataProviderRef dataProvider = CGDataProviderCreateWithCFData((CFDataRef)data);
CGPDFDocumentRef document = CGPDFDocumentCreateWithProvider(dataProvider);

//Create the pdf context
CGPDFPageRef page = CGPDFDocumentGetPage(document, 1); //Pages are numbered starting at 1
CGRect pageRect = CGPDFPageGetBoxRect(page, kCGPDFMediaBox);
CFMutableDataRef mutableData = CFDataCreateMutable(NULL, 0);



CFMutableDictionaryRef ref = CFDictionaryCreateMutable(NULL,
                                                       0,
                                                       &kCFTypeDictionaryKeyCallBacks,
                                                       &kCFTypeDictionaryValueCallBacks);

CFDictionarySetValue(ref, kCGPDFContextUserPassword, (__bridge CFStringRef)password);
CFDictionarySetValue(ref, kCGPDFContextOwnerPassword, (__bridge CFStringRef)password);

CGDataConsumerRef dataConsumer = CGDataConsumerCreateWithCFData(mutableData);
CGContextRef pdfContext = CGPDFContextCreate(dataConsumer, &pageRect, ref);

if (CGPDFDocumentGetNumberOfPages(document) > 0) {
    //Draw the page onto the new context
    page = CGPDFDocumentGetPage(document, 1); //Pages are numbered starting at 1

    CGPDFContextBeginPage(pdfContext, NULL);
    CGContextDrawPDFPage(pdfContext, page);
    CGPDFContextEndPage(pdfContext);

} else {
    NSLog(@"Failed to create the document");
}

CGContextRelease(pdfContext); //Release before writing data to disk.

//Write to disk
[(__bridge NSData *)mutableData writeToFile:path atomically:YES];

//Clean up
CGDataProviderRelease(dataProvider); //Release the data provider
CGDataConsumerRelease(dataConsumer);
CGPDFDocumentRelease(document);
CFRelease(mutableData);}

This does set a password and save the file but with only one page. How would I make it create a copy of the entire PDF?

From what I can see this script is going to need to loop through all pages and draw the PDF page by page. Is there a way I can simply duplicate the PDF and set a password rather than having to draw each page?

Thanks in advance

Upvotes: 2

Views: 449

Answers (1)

Mihai Iancu
Mihai Iancu

Reputation: 1828

On iOS you cannot simply duplicate the file and set a password. You have to loop through all the pages of the source document and draw them in the new document.
The problem with this approach is that only page content is transfered to the new document. If the source document contains bookmarks, annotations, form fields, attachments then they will not be transfered to the new document. There is no solution for this at the moment.

Upvotes: 3

Related Questions