美文网首页iOS开发笔记本
【iOS】读取一个带有加密印章的PDF

【iOS】读取一个带有加密印章的PDF

作者: zhangPeng丶 | 来源:发表于2017-08-29 11:27 被阅读29次

简书http://www.jianshu.com/u/5690b3ad0a6f
Bloghttp://blog.zhangpeng.site
GitHubhttps://github.com/fullstack-zhangpeng

ShowPDFDemo

一个显示PDF的Demo,可以显示出PDF上的加密印章。

Description

工作中,有时会遇上含加密印章的PDF文档,这时如果直接用UIWebView或者WKWebView打开,那加密的印章便不能显示。本Demo通过pdf.js解决此问题。

Demo

https://github.com/Zhang1Peng/ShowPDFDemo.git

实现步骤

1.本Demo采用这时如果直接用UIWebView或者WKWebView完成,引入WebKit/WebKit.h

#import <WebKit/WebKit.h>

2.Demo中使用的宏

#define kScreenW [UIScreen mainScreen].bounds.size.width
#define kScreenH [UIScreen mainScreen].bounds.size.height

#define DOCUMENTS_DIRECTORY [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject]

3.搭建UI

WKWebViewConfiguration *config = [[WKWebViewConfiguration alloc] init];

WKUserContentController* wkUController = [[WKUserContentController alloc]init];

config.userContentController = wkUController;

// 注入JS对象名称AppModel,当JS通过AppModel来调用时,我们可以在WKScriptMessageHandler代理中接收到
// 此处是为了得到PDF加载完成或失败的反馈
[config.userContentController addScriptMessageHandler:self name:@"AppModel"];

// 改变页面内容宽度,适配屏幕大小
NSString *js = @"var meta = document.createElement('meta'); meta.setAttribute('name', 'viewport'); meta.setAttribute('content', 'width=device-width'); document.getElementsByTagName('head')[0].appendChild(meta);";

WKUserScript *wkUserScript = [[WKUserScript alloc] initWithSource:js
                                                    injectionTime:WKUserScriptInjectionTimeAtDocumentEnd
                                                 forMainFrameOnly:YES];
[wkUController addUserScript:wkUserScript];


WKWebView *webView = [[WKWebView alloc] initWithFrame:CGRectMake(0, 0, kScreenW, kScreenH - 64)
                                        configuration:config];
webView.backgroundColor = [UIColor whiteColor];
webView.UIDelegate = self;
webView.navigationDelegate = self;
[self.view addSubview:webView];

4.下载PDF

NSString *urlStr = @"http://oshsanwqi.bkt.clouddn.com/jianLi_zhangpeng.pdf";

NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:urlStr]];

NSURLSession *session = [NSURLSession sharedSession];

NSURLSessionDataTask *sessionDataTask = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
    
    NSLog(@"从服务器获取到pdf数据");
    
    //对从服务器获取到的数据data进行相应的处理:
    dispatch_async(dispatch_get_main_queue(), ^{
        
        NSString* path = [DOCUMENTS_DIRECTORY stringByAppendingPathComponent:@"contract.pdf"];
        
        NSFileManager* fm = [NSFileManager defaultManager];
        
        if ([fm fileExistsAtPath:path]) {
            
            [fm removeItemAtPath:path error:nil];
        }
        
        BOOL success =  [data writeToFile:path atomically:YES];
        
        if (success) {
            
            NSLog(@"保存成功");
            
            NSURL *baseURL = [NSURL fileURLWithPath:[self getHtmlBasePath]];
            
            NSString *path = [self getHtmlPath];

            NSString *htmlStr = [NSString stringWithContentsOfFile:path
                                                          encoding:NSUTF8StringEncoding
                                                             error:nil];

            [self.webView loadHTMLString:htmlStr baseURL:baseURL];
        }
    });
    
}];

[sessionDataTask resume];

5.适配 iOS 8

在iOS8上,html及js文件的路径为temp目录下,ios9及以上则在bundle里

- (NSString*)getHtmlBasePath {
    NSString *basePath = @"";
    
    if ([[[UIDevice currentDevice]systemVersion]floatValue]<9.0) {
        basePath = NSTemporaryDirectory();
    }else{
        basePath = [[NSBundle mainBundle] bundlePath];
    }
    return basePath;
}

- (NSString*)getHtmlPath{
    //在iOS8上,html及js文件的路径为temp目录下,ios9及以上则在bundle里
    NSString* path = @"";
    
    if ([[[UIDevice currentDevice]systemVersion] floatValue] < 9.0) {
        
        path = [self copyHtmlToTemp];
        
    }else{
        
        path = [[NSBundle mainBundle] pathForResource:@"index" ofType:@".html"];
    }
    return path;
}

//在iOS8上,html及js文件要放到temp目录下才能正常访问,ios9及以上不用
- (NSString*)copyHtmlToTemp {
    
    NSString* htmlPath = [[NSBundle mainBundle] pathForResource:@"index" ofType:@".html"];
    NSString* compatibilityJSPath = [[NSBundle mainBundle] pathForResource:@"compatibility" ofType:@".js"];
    NSString* customviewJSPath = [[NSBundle mainBundle] pathForResource:@"customview" ofType:@".js"];
    NSString* minimalCSSPath = [[NSBundle mainBundle] pathForResource:@"minimal" ofType:@".css"];
    NSString* pdfJSPath = [[NSBundle mainBundle] pathForResource:@"pdf" ofType:@".js"];
    NSString* pdfWorkerJSPath = [[NSBundle mainBundle] pathForResource:@"pdf.worker" ofType:@".js"];
    
    NSString* tempPath = NSTemporaryDirectory();
    
    NSString* htmlTempPath = [tempPath stringByAppendingPathComponent:@"index.html"];
    NSString* compatibilityJSTempPath = [tempPath stringByAppendingPathComponent:@"compatibility.js"];
    NSString* customviewJSTempPath = [tempPath stringByAppendingPathComponent:@"customview.js"];
    NSString* minimalCSSTempPath = [tempPath stringByAppendingPathComponent:@"minimal.css"];
    NSString* pdfJSTempPath = [tempPath stringByAppendingPathComponent:@"pdf.js"];
    NSString* pdfWorkerJSTempPath = [tempPath stringByAppendingPathComponent:@"pdf.worker.js"];
    
    NSFileManager* fm = [NSFileManager defaultManager];
    
    if (![fm fileExistsAtPath:htmlTempPath]) {
        [fm copyItemAtPath:htmlPath toPath:htmlTempPath error:nil];
    }
    if (![fm fileExistsAtPath:compatibilityJSTempPath]) {
        [fm copyItemAtPath:compatibilityJSPath toPath:compatibilityJSTempPath error:nil];
    }
    if (![fm fileExistsAtPath:customviewJSTempPath]) {
        [fm copyItemAtPath:customviewJSPath toPath:customviewJSTempPath error:nil];
    }
    if (![fm fileExistsAtPath:minimalCSSTempPath]) {
        [fm copyItemAtPath:minimalCSSPath toPath:minimalCSSTempPath error:nil];
    }
    if (![fm fileExistsAtPath:pdfJSTempPath]) {
        [fm copyItemAtPath:pdfJSPath toPath:pdfJSTempPath error:nil];
    }
    if (![fm fileExistsAtPath:pdfWorkerJSTempPath]) {
        [fm copyItemAtPath:pdfWorkerJSPath toPath:pdfWorkerJSTempPath error:nil];
    }
    
    return htmlTempPath;
}

6.读取PDF

在WKWebView的代理中读取PDF

- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation {
    
    [self loadPDF];
}

- (void)loadPDF {
    
    NSString* path = [DOCUMENTS_DIRECTORY stringByAppendingPathComponent:@"contract.pdf"];
    
    NSData* data = [NSData dataWithContentsOfFile:path
                                          options:NSDataReadingMappedAlways
                                            error:nil];
    
    NSString *paraStr = [data base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithCarriageReturn];
    
    NSString *js = [NSString stringWithFormat:@"loadMyJS('%@')",paraStr];
    //NSLOG(@"%@",method);
    
    [self.webView evaluateJavaScript:js completionHandler:^(id _Nullable response, NSError * _Nullable error) {
        
        if (error) {
            
            NSLog(@"%@", error);
            
            NSLog(@"当前手机系统版本较低,不支持查看,请升级系统或者到PC端查看。");
        }
    }];
}

7.在WKScriptMessageHandler中监听PDF是否读取成功

- (void)userContentController:(WKUserContentController *)userContentController
      didReceiveScriptMessage:(WKScriptMessage *)message {
    if ([message.name isEqualToString:@"AppModel"]) {  //和customview.js文件交互,js调oc的代码
        
        // 打印所传过来的参数,只支持NSNumber, NSString, NSDate, NSArray, NSDictionary, and NSNull类型
        if ([message.body[@"code"] isEqualToString:@"00000"]) {
            
            NSLog(@"%@", message.body[@"msg"]);
        }
    }
}

8.PDF是否读取成功是在customview.js中通知控制器的

function handlePages(page)
{
  //create new canvas
  var viewport = page.getViewport(1);
  var canvas = document.createElement( "canvas" );
  canvas.style.display="block";
  
  var context = canvas.getContext('2d');
  canvas.height = viewport.height;
  canvas.width = viewport.width;

  //render page
  page.render({canvasContext: context, viewport: viewport});

  //add canvas to body
  document.body.appendChild(canvas);

  //render new page
  pageNum++;
    if(pdfDoc!=null && pageNum<=numPages){
        pdfDoc.getPage(pageNum).then(handlePages);
        // PDF 加载失败
    }else{
        console.log("pdf load complete");
        // PDF 加载完毕,body的内容可以根据具体的业务需求进行修改
        window.webkit.messageHandlers.AppModel.postMessage({
                                                           code: "00000",
                                                           msg: "pdf load complete"
                                                           });//和wkWebView交互
    }

}

相关文章

网友评论

本文标题:【iOS】读取一个带有加密印章的PDF

本文链接:https://www.haomeiwen.com/subject/omlodxtx.html