본문 바로가기
프로그래밍/Xcode-iOS

iOS WKWebView PDF Download Viewer

by Mr-후 2020. 9. 2.
반응형

어쩐지 쉽게 해결이 되었다고 생각이 들긴했지만 구석구석 문제점이 하나씩 나오기도 한다. 이번에는 멀쩡하게 잘 사용하던 pdf링크에 대한 문제다. 

일반적으로 서버의 특정 URL을 호출하면 서버에서 파라미터에 맞게 PDF 파일을 읽어 파일을 내려주는 방식인데 WKWebView에서는 pdf자체의 바이너리를 읽어들이는 현상이 나타났다. 

따라서 서버에서 내려주는 pdf파일을 단말의 캐시폴더에 저장하고 저장된 파일을 읽어와서 보여주는 방식으로 변경이 필요해서 검색을 하고 WKWebView Interface를 살펴보니 답이 나왔다. 

WKWebView의 loadData:MIMEType:charaterEncodingName:baseUrl을 이용하고 서버에서 내려주는 파일은 NSURLSession을 이용해서 다운로드 후 저장하는 방식을 사용하였다. 다음은 그 코드들이다. 

웹뷰의 dicidePolicyForNavigationAction에서 load Url에 대해 분기를 처리한 다음 downloadFileFromURL을 호출하는 코드 예시. 

    if ([reqUrl rangeOfString:@".me/download/?type="].location != NSNotFound) {
        [self downloadFileFromURL:[NSURL URLWithString:reqUrl] completion:^(NSString *filepath) {
            dispatch_after(dispatch_time(DISPATCH_TIME_NOW, .2f * NSEC_PER_SEC), dispatch_get_main_queue(), ^(void){
                [self viewDownloadFile:filepath];
            });
        }];
        decisionHandler(WKNavigationActionPolicyCancel);
        return;
    }

 

파일을 다운르도 처리한다. 

/**
 * 파일다운로드 처리
 * add by logan 2020.09.02
 */
- (void)downloadFileFromURL:(NSURL *)url completion:(void (^)(NSString *filepath))completion {
       NSURLSessionConfiguration *sessionConfiguration = [NSURLSessionConfiguration defaultSessionConfiguration];
       NSURLSession *session = [NSURLSession sessionWithConfiguration:sessionConfiguration];
       NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
       request.HTTPMethod = @"GET";

       NSURLSessionDataTask *postDataTask = [session dataTaskWithRequest:request
                                                       completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
           if (!error) {
               dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
                   NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
                   NSString *documentsDirectory = [paths objectAtIndex:0];
                   NSString *dataPath = [documentsDirectory stringByAppendingPathComponent:@"linkedin-file-export.pdf"];

                   [data writeToFile:dataPath atomically:YES];

                   completion(dataPath);
               });
           }
           else {
               NSLog(@"%@",error);
               completion([NSString string]);
           }
       }];
       [postDataTask resume];
}

 

다운로드 된 파일의 경로를 획득하여 viewDownlaodFile을 호출한다. 

    NSData *data = [NSData dataWithContentsOfFile:path];
    if ([data length] > 0) {
        [self.webView loadData:data MIMEType:@"application/pdf" characterEncodingName:@"UTF-8" baseURL:[NSURL URLWithString:path]];
    }

 

폰의 경로에 저장된 pdf파일을 NSData로 변환하고 webView의 loadData를 통해 로드하는 방식으로 구현을 했다. 이때 깔끔하도록 모달창으로 팝업을 뛰어 내용을 보여주는 방식으로 변경하였다. 

 

 

 

 

반응형