How to Retrieve a File Using Wkwebview

How can I retrieve a file using WKWebView?

Right now, WKWebView instances will ignore any of the default networking storages (NSURLCache, NSHTTPCookieStorage, NSCredentialStorage) and also the standard networking classes you can use to customize the network requests (NSURLProtocol, etc.).

So the cookies of the WKWebView instance are not stored in the standard Cookie storage of your App, and so NSURLSession/NSURLConnection which only uses the standard Cookie storage has no access to the cookies of WKWebView (and exactly this is probably the problem you have: the „login status“ is most likely stored in a cookie, but NSURLSession/NSURLConnection won’t see the cookie).

The same is the case for the cache, for the credentials etc. WKWebView has its own private storages and therefore does not play well with the standard Cocoa networking classes.

You also can’t customize the requests (add your own custom HTTP headers, modify existing headers, etc), use your own custom URL schemes etc, because also NSURLProtocol is not supported by WKWebView.

So right now WKWebView is pretty useless for many Apps, because it does not participate with the standard networking APIs of Cocoa.

I still hope that Apple will change this until iOS 8 gets released, because otherwise WKWebView will be useless for many Apps, and we are probably stick with UIWebView a little bit longer.

So send bug reports to Apple, so Apple gets to know that these issues are serious and needs to be fixed.

Load local web files & resources in WKWebView

Updated for Swift 4, Xcode 9.3


This methods allows WKWebView to properly read your hierarchy of directories and sub-directories for linked CSS, JS and most other files. You do NOT need to change your HTML, CSS or JS code.

Solution (Quick)

  1. Add the web folder to your project (File > Add Files to Project)

    • Copy items if needed
    • Create folder references *
    • Add to targets (that are applicable)
  2. Add the following code to the viewDidLoad and personalize it to your needs:

    let url = Bundle.main.url(forResource: "index", withExtension: "html", subdirectory: "website")!
    webView.loadFileURL(url, allowingReadAccessTo: url)
    let request = URLRequest(url: url)
    webView.load(request)

Solution (In-Depth)

Step 1

Import the folder of local web files anywhere into your project. Make sure that you:

Xcode > File > Add Files to "Project"

☑️ Copy items if needed

☑️ Create folder references (not "Create groups")

☑️ Add to targets

Step 2

Go to the View Controller with the WKWebView and add the following code to the viewDidLoad method:

let url = Bundle.main.url(forResource: "index", withExtension: "html", subdirectory: "website")!
webView.loadFileURL(url, allowingReadAccessTo: url)
let request = URLRequest(url: url)
webView.load(request)
  • index – the name of the file to load (without the .html extension)
  • website – the name of your web folder (index.html should be at the root of this directory)

Conclusion

The overall code should look something like this:

import UIKit
import WebKit

class ViewController: UIViewController, WKUIDelegate, WKNavigationDelegate {

@IBOutlet weak var webView: WKWebView!

override func viewDidLoad() {
super.viewDidLoad()

webView.uiDelegate = self
webView.navigationDelegate = self

let url = Bundle.main.url(forResource: "index", withExtension: "html", subdirectory: "Website")!
webView.loadFileURL(url, allowingReadAccessTo: url)
let request = URLRequest(url: url)
webView.load(request)
}

}

If any of you have further questions about this method or the code, I'll do my best to answer!

Downloading files WKWebView ios

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);
}
}


Related Topics



Leave a reply



Submit