Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Downloading files WKWebView ios

I'm in the progress of migrating my app from UIWebView to WKWebView. All is going well and working as I tinker more with it. However, I notice now that I can't download forum attachments.

I'm using HCDownload, and thus far has always worked perfect for me, so I know it's not on that end. I believe its the request, but I cant figure it out.

I know the following:

UIWebView => WKWebView Equivalent
--------------------------------------------------------------
didFailLoadWithError => didFailNavigation
webViewDidFinishLoad => didFinishNavigation
webViewDidStartLoad => didStartProvisionalNavigation
shouldStartLoadWithRequest => decidePolicyForNavigationAction

So with that known I am trying below:

- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler {

    NSURLRequest *request = navigationAction.request;
    NSURL *fileURl = [request URL];
    NSString *externalFileExtension = [fileURl pathExtension];
    NSString *internalFileExtension = [[fileURl absoluteString] pathExtension];

    HCDownloadViewController *dlvc = [[HCDownloadViewController alloc] init];
    UINavigationController *vc = [[UINavigationController alloc] initWithRootViewController:dlvc];
    dlvc.delegate = self;
    vc.transitioningDelegate  = self;

    if (navigationAction.navigationType == WKNavigationTypeLinkActivated) {

        //External file extensions
        if ([fileExtensions containsObject:[externalFileExtension lowercaseString]]) {
            [dlvc downloadURL:fileURl userInfo:nil];
            [self presentViewController:vc animated:YES completion:nil];
            [vc release];

            NSLog(@"externalURL is %@", fileURl);
            decisionHandler(WKNavigationActionPolicyCancel);
            return;
        }

        //Internal file links
        if ([fileExtensions containsObject:[internalFileExtension lowercaseString]]) {
            [self presentViewController:vc animated:YES completion:nil];
            [dlvc downloadURL:fileURl userInfo:nil];
            [vc release];

            NSLog(@"internalURL is %@", fileURl);
            decisionHandler(WKNavigationActionPolicyCancel);
            return;

        }
}

It will fire my download controller by finding the file extension, but instead it downloads the index.php, not the file.

Example url:

https://example.com/index.php?app=core&module=attach&section=attach&attach_id=1234=example.zip;

What am I doing wrong. It worked fine before in UIWebView and I know things are done differently. But how can it download something from say dropbox just fine, but an attached file on a forum gets goofed up.

Any help would be appreciated

like image 373
ChrisOSX Avatar asked Dec 18 '22 21:12

ChrisOSX


2 Answers

Well heres what I ended up with, and all seems to be working fine.

- (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler{
    NSHTTPURLResponse *response = (NSHTTPURLResponse *)navigationResponse.response;
    NSArray *cookies =[NSHTTPCookie cookiesWithResponseHeaderFields:[response allHeaderFields] forURL:response.URL];
    for (NSHTTPCookie *cookie in cookies) {
        [[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookie:cookie];
    }

    decisionHandler(WKNavigationResponsePolicyAllow);
    //NSLog(@"decidePolicyForNavigationResponse");
}


//Download manager
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler {

    NSURLRequest *request = navigationAction.request;
    fileURL = request.URL;

    HCDownloadViewController *dlvc = [[HCDownloadViewController alloc] init];
    UINavigationController *vc = [[UINavigationController alloc] initWithRootViewController:dlvc];
    vc.transitioningDelegate  = self;
    dlvc.delegate = self;

    if (navigationAction.navigationType == WKNavigationTypeLinkActivated) {

        //Internal file links
        NSString *internalFileExtension = fileURL.absoluteString.pathExtension;
        if ([fileExtensions containsObject:[internalFileExtension lowercaseString]]) {

            //Fire download
            [dlvc downloadURL:fileURL userInfo:nil];
            [self presentViewController:vc animated:YES completion:nil];
            [vc release];

            NSLog(@"internalURL is %@", fileURL);
            if (decisionHandler) {
                decisionHandler(WKNavigationActionPolicyCancel);
            }
            return;
        }

        //External file extensions
        NSString *externalFileExtension = fileURL.pathExtension;
        if ([fileExtensions containsObject:[externalFileExtension lowercaseString]]) {

            //Fire download
            [dlvc downloadURL:fileURL userInfo:nil];
            [self presentViewController:vc animated:YES completion:nil];
            [vc release];

            NSLog(@"externalURL is %@", fileURL);
            if (decisionHandler) {
                decisionHandler(WKNavigationActionPolicyCancel);
            }
            return;
        }
    }

    if (decisionHandler) {
        decisionHandler(WKNavigationActionPolicyAllow);
    }
}
like image 141
ChrisOSX Avatar answered Dec 21 '22 10:12

ChrisOSX


You are probably downloading a not-authorized page because your WKWebView and HCDownload instances don't share cookie sessions like UIWebView could. That's a necessary trade-off for the WK2 process model's speed & security improvements.

I added downloading to my WKWebKit-based OSX/Swift mini-browser by implementing _WKDownloadDelegate. Its a totally undocumented private protocol as of El Cap and iOS9. It lets your navigation delegate call decisionHandler(_WKNavigationResponsePolicyBecomeDownload) whereby WebKit will download in the background after giving you the chance to pick/change a file name. I haven't the foggiest idea on how to implement a file picker in iOS yet, nor if using that protocol would be allowed by the App Store reviewers. But my app now does correctly handle downloading from session-authentication sites like your PHP forum.

like image 21
kfix Avatar answered Dec 21 '22 09:12

kfix