Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/94.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Iphone 在iOS上合并PDF文件_Iphone_Ios_Cocoa Touch_Ipad_Pdf - Fatal编程技术网

Iphone 在iOS上合并PDF文件

Iphone 在iOS上合并PDF文件,iphone,ios,cocoa-touch,ipad,pdf,Iphone,Ios,Cocoa Touch,Ipad,Pdf,在iOS中有没有合并PDF文件的方法,即在另一个文件的末尾附加一个文件的页面并将其保存到磁盘?我相信这正是您想要的,并且有一个免费版本 我想出了这个解决方案: // Documents dir NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString *documentsDirectory = [paths objectAtIndex:0];

在iOS中有没有合并PDF文件的方法,即在另一个文件的末尾附加一个文件的页面并将其保存到磁盘?

我相信这正是您想要的,并且有一个免费版本

我想出了这个解决方案:

// Documents dir
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];

// File paths
NSString *pdfPath1 = [documentsDirectory stringByAppendingPathComponent:@"1.pdf"];
NSString *pdfPath2 = [documentsDirectory stringByAppendingPathComponent:@"2.pdf"];
NSString *pdfPathOutput = [documentsDirectory stringByAppendingPathComponent:@"out.pdf"];

// File URLs
CFURLRef pdfURL1 = (CFURLRef)[[NSURL alloc] initFileURLWithPath:pdfPath1];
CFURLRef pdfURL2 = (CFURLRef)[[NSURL alloc] initFileURLWithPath:pdfPath2];
CFURLRef pdfURLOutput = (CFURLRef)[[NSURL alloc] initFileURLWithPath:pdfPathOutput];

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

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

// 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 (%i)...", 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 (%i)...", 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
CFRelease(pdfURL1);
CFRelease(pdfURL2);
CFRelease(pdfURLOutput);
CGPDFDocumentRelease(pdfRef1);
CGPDFDocumentRelease(pdfRef2);
CGContextRelease(writeContext);
//文档目录
NSArray*Path=NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,是);
NSString*documentsDirectory=[paths objectAtIndex:0];
//文件路径
NSString*pdfPath1=[DocumentsDirectoryStringByAppendingPathComponent:@“1.pdf”];
NSString*pdfPath2=[DocumentsDirectoryStringByAppendingPathComponent:@“2.pdf”];
NSString*pdfPathOutput=[DocumentsDirectoryStringByAppendingPathComponent:@“out.pdf”];
//文件URL
CFURLRef pdfURL1=(CFURLRef)[[NSURL alloc]initFileURLWithPath:pdfPath1];
CFURLRef pdfURL2=(CFURLRef)[[NSURL alloc]initFileURLWithPath:pdfPath2];
CFURLRef Pdforloutput=(CFURLRef)[[NSURL alloc]initFileURLWithPath:pdfPathOutput];
//文件引用
CGPDFDocumentRef pdfRef1=CGPDFDocumentCreateWithURL((CFURLRef)pdfURL1);
CGPDFDocumentRef pdfRef2=CGPDFDocumentCreateWithURL((CFURLRef)pdfURL2);
//页数
NSInteger numberOfPages1=CGPDFDocumentGetNumberOfPages(pdfRef1);
NSInteger numberOfPages2=CGPDFDocumentGetNumberOfPages(pdfRef2);
//创建输出上下文
CGContextRef writeContext=CGPDFContextCreateWithURL(pdfURLOutput,NULL,NULL);
//循环变量
CGPDFPageRef页面;
CGRect媒体盒;
//阅读第一份PDF并生成输出页面
NSLog(@“从PDF 1(%i)…生成页面”,numberOfPages1);

对于(int i=1;i我对Jonathan的代码进行了一些重构,以加入任何大小的PDF文件:

+ (NSString *)joinPDF:(NSArray *)listOfPaths {
    // File paths
    NSString *fileName = @"ALL.pdf";
    NSString *pdfPathOutput = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0] stringByAppendingPathComponent:fileName];

    CFURLRef pdfURLOutput = (  CFURLRef)CFBridgingRetain([NSURL fileURLWithPath:pdfPathOutput]);

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

    for (NSString *source in listOfPaths) {
        CFURLRef pdfURL = (  CFURLRef)CFBridgingRetain([[NSURL alloc] initFileURLWithPath:source]);

        //file ref
        CGPDFDocumentRef pdfRef = CGPDFDocumentCreateWithURL((CFURLRef) pdfURL);
        numberOfPages = CGPDFDocumentGetNumberOfPages(pdfRef);

        // Loop variables
        CGPDFPageRef page;
        CGRect mediaBox;

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

        CGPDFDocumentRelease(pdfRef);
        CFRelease(pdfURL);
    }
    CFRelease(pdfURLOutput);

    // Finalize the output file
    CGPDFContextClose(writeContext);
    CGContextRelease(writeContext);

    return pdfPathOutput;
}
+(NSString*)joinPDF:(NSArray*)路径列表{
//文件路径
NSString*fileName=@“ALL.pdf”;
NSString*pdfPathOutput=[[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES)对象索引:0]stringByAppendingPathComponent:fileName];
CFURLRef Pdforloutput=(CFURLRef)CfBrigingRetain([NSURL fileURLWithPath:pdfPathOutput]);
NSInteger numberOfPages=0;
//创建输出上下文
CGContextRef writeContext=CGPDFContextCreateWithURL(pdfURLOutput,NULL,NULL);
for(NSString*路径列表中的源){
CFURLRef pdfURL=(CFURLRef)CfBrigingRetain([[NSURL alloc]initFileURLWithPath:source]);
//文件引用
CGPDFDocumentRef pdfRef=CGPDFDocumentCreateWithURL((CFURLRef)pdfURL);
numberOfPages=CGPDFDocumentGetNumberOfPages(pdfRef);
//循环变量
CGPDFPageRef页面;
CGRect媒体盒;
//阅读第一份PDF并生成输出页面
DLog(@“从PDF 1生成页面(%@)…”,来源);

对于(iTi=1;i我在这里推广我自己的库……但是我有一个免费的PDF读写库,我最近展示了如何在iOS上下文中使用。它非常适合合并PDF和操作它们,并且用一个相对较小的内存签名来做。考虑使用它,在这里看到一个例子。再次,是我在推广我自己的库,DAK也这样做。将此建议置于正确的上下文中。

我的解决方案基于@matsoftware创建的解决方案

我为我的解决方案创建了一个代码段:

+(void)组合EPDFURL:(NSArray*)PDFURLs writeToURL:(NSURL*)URL
{
CGContextRef context=CGPDFContextCreateWithURL(((uu桥CFURLRef)URL,NULL,NULL);
用于(NSURL*PDFURL在PDFURL中){
CGPDFDocumentRef document=CGPDFDocumentCreateWithURL(((uu桥CFURLRef)PDFURL);
大小\u t numberOfPages=CGPDFDocumentGetNumberOfPages(文档);

对于(size_t pageNumber=1;pageNumber我想用Swift分享答案,因为我在Swift中寻找答案,但找不到,不得不翻译。此外,我的答案使用了每个单独的pdf的数组,并循环生成完整的pdf。我在这方面相当新,所以任何建议都可以来吧

    let file = "fileName.pdf"
    guard var documentPaths = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true).first else {
        NSLog("Doh - can't find that path")
        return
    }
    documentPaths = documentPaths.stringByAppendingString(file)
    print(documentPaths)

    let fullPDFOutput: CFURLRef = NSURL(fileURLWithPath: documentPaths)

    let writeContext = CGPDFContextCreateWithURL(fullPDFOutput, nil, nil)

    for pdfURL in pdfPagesURLArray {
        let pdfPath: CFURLRef = NSURL(fileURLWithPath: pdfURL)
        let pdfReference = CGPDFDocumentCreateWithURL(pdfPath)
        let numberOfPages = CGPDFDocumentGetNumberOfPages(pdfReference)
        var page: CGPDFPageRef
        var mediaBox: CGRect

        for index in 1...numberOfPages {
可以像这样强制展开:
page=CGPDFDocumentGetPage(pdfReference,index)!
但要继续采用最佳做法:

        guard let getCGPDFPage = CGPDFDocumentGetPage(pdfReference, index) else {
                NSLog("Error occurred in creating page")
                return
            }
            page = getCGPDFPage
            mediaBox = CGPDFPageGetBoxRect(page, .MediaBox)
            CGContextBeginPage(writeContext, &mediaBox)
            CGContextDrawPDFPage(writeContext, page)
            CGContextEndPage(writeContext)
        }
    }
    NSLog("DONE!")

    CGPDFContextClose(writeContext);

    NSLog(documentPaths)

我在swift 3中的职能:

// sourcePdfFiles is array of source file full paths, destPdfFile is dest file full path
func mergePdfFiles(sourcePdfFiles:[String], destPdfFile:String) {

    guard UIGraphicsBeginPDFContextToFile(destPdfFile, CGRect.zero, nil) else {
        return
    }
    guard let destContext = UIGraphicsGetCurrentContext() else {
        return
    }

    for index in 0 ..< sourcePdfFiles.count {
        let pdfFile = sourcePdfFiles[index]
        let pdfUrl = NSURL(fileURLWithPath: pdfFile)
        guard let pdfRef = CGPDFDocument(pdfUrl) else {
            continue
        }

        for i in 1 ... pdfRef.numberOfPages {
            if let page = pdfRef.page(at: i) {
                var mediaBox = page.getBoxRect(.mediaBox)
                destContext.beginPage(mediaBox: &mediaBox)
                destContext.drawPDFPage(page)
                destContext.endPage()
            }
        }
    }

    destContext.closePDF()
    UIGraphicsEndPDFContext()
}
//sourcePdfFiles是源文件完整路径的数组,destpffile是dest文件完整路径
func mergePffiles(sourcePffiles:[String],destpffile:String){
guard UIGraphicsBeginPDFContextToFile(destpffile,CGRect.zero,nil)else{
返回
}
guard let destContext=UIGraphicsGetCurrentContext()else{
返回
}
对于0中的索引。
Swift 5:

像这样合并PDF以保持链接等

func mergePdf(data: Data, otherPdfDocumentData: Data) -> PDFDocument {
    // get the pdfData
    let pdfDocument = PDFDocument(data: data)!
    let otherPdfDocument = PDFDocument(data: otherPdfDocumentData)!
    
    // create new PDFDocument
    let newPdfDocument = PDFDocument()

    // insert all pages of first document
    for p in 0..<pdfDocument.pageCount {
    let page = pdfDocument.page(at: p)!
        newPdfDocument.insert(page, at: newPdfDocument.pageCount)
    }

    // insert all pages of other document
    for q in 0..<otherPdfDocument.pageCount {
        let page = otherPdfDocument.page(at: q)!
        newPdfDocument.insert(page, at: newPdfDocument.pageCount)
    }
    return newPdfDocument
}
保存您的pdf。 首先转换
newPdfDocument
,如下所示:

let documentDataForSaving = newPdfDocument.dataRepresentation()
documentDataForSaving
放入以下功能中: 使用保存功能:

let urlWhereTheFileIsSaved = writeDataToTemporaryDirectory(withFilename: "My File Name", inFolder: nil, data: documentDataForSaving)
您可能希望避免在文件名中使用
/
,并且不要使其长度超过256个字符

保存功能:


这是一个很好的显示pdf的库,但它不支持合并AFAICT。看起来链接已断开。修改代码以便发布每个文档(甚至每个x-pages左右)应该不会太难,如果您一次将每个页面写入磁盘…见鬼,您可以一次读取和释放一个页面!这是速度和内存之间的折衷…这会起作用!尽管我还找不到实现的方法。在您使用let documentDataForSaving = newPdfDocument.dataRepresentation()
let urlWhereTheFileIsSaved = writeDataToTemporaryDirectory(withFilename: "My File Name", inFolder: nil, data: documentDataForSaving)
// Export PDF to directory, e.g. here for sharing
    func writeDataToTemporaryDirectory(withFilename: String, inFolder: String?, data: Data) -> URL? {
        do {
            // get a directory
            var temporaryDirectory = FileManager.default.temporaryDirectory // for e.g. sharing
            // FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).last! // to make it public in user's directory (update plist for user access) 
            // FileManager.default.urls(for: .libraryDirectory, in: .userDomainMask).last! // to hide it from any user interactions) 
            // do you want to create subfolder?
            if let inFolder = inFolder {
                temporaryDirectory = temporaryDirectory.appendingPathComponent(inFolder)
                if !FileManager.default.fileExists(atPath: temporaryDirectory.absoluteString) {
                    do {
                        try FileManager.default.createDirectory(at: temporaryDirectory, withIntermediateDirectories: true, attributes: nil)
                    } catch {
                        print(error.localizedDescription);
                    }
                }
            }
            // name the file
            let temporaryFileURL = temporaryDirectory.appendingPathComponent(withFilename)
            print("writeDataToTemporaryDirectory at url:\t\(temporaryFileURL)")
            try data.write(to: temporaryFileURL)
            return temporaryFileURL
        } catch {
            print(error)
        }
        return nil
    }