Loading local images into WKWebView

Viewed 13658

I'm trying to get WKWebView to display locally downloaded images in a WKWebView. The webview normally displays HTML, which is retrieved remotely. The contents of the HTML can sometimes contain remote links to images. My app parses the HTML and looks for these HTML tags, downloads the file it is referencing and subsequently replaces the remote link with a local one.

Normally speaking, this wouldn't be very difficult but the images aren't being displayed, presumably due to the images and the local HTML files for the webview being in two separate directories (the documents directory and the app bundle directory respectively). I've seen people suggest moving the download destination of the images to the same directory as where the HTML files are but this isn't an option for me as I don't want to start mixing up files downloaded by the user with local assets.

What would be my best course of action here?

4 Answers

To display cached HTML referencing cached resources in a WKWebView:

  1. For each of the resources within your HTML content string, cache it into the directory as provided by NSTemporaryDirectory(). So an image tag like:

    ...<img src='https://www.myimage.com/example_image.png'/>...

    should be cached and replaced into something like this:

    ...<img src='/private/var/mobile/Containers/Data/Application/527CF4FC-9319-4DFF-AB55-9E276890F5DC/tmp/example_image.png'/>...

  2. Now cache the HTML content string with the replaced resource URLs. It must also be cached in the directory provided by NSTemporaryDirectory(). One difference here is that it must be cached (and later referenced) using the file:// protocol as a restriction of caching the string using NSData (see sample code).

    For example file:///private/var/mobile/Containers/Data/Application/527CF4FC-9319-4DFF-AB55-9E276890F5DC/tmp/my_html_content_string.html

A few things to point out:

  • You cannot load the HTML as a raw string (loadHTMLString:baseURL:).
  • You cannot reference the cached resource within your HTML string using the file:// protocol. That may work in a UIWebView, but will not work in the WKWebView.

Objective-C

// To cache the HTML string:
NSString *HTML = <HTML CONTENT WITH CACHED RESOURCES>;
NSData *data = [HTML dataUsingEncoding: NSUTF8StringEncoding];
[data writeToURL: cachedHTMLURL atomically: YES];

// To load the store HTML file:
[myWKWebView loadRequest: [NSURLRequest requestWithURL: cachedHTMLURL]]; // (file://.../tmp/my_html_content_string.html)

Swift

// To cache the HTML string:
let HTML = <HTML CONTENT WITH CACHED RESOURCES>
let data = HTML.data(using: String.Encoding.utf8)
do {
    try data.write(to: cachedHTMLURL, options: .atomic)
} catch {
    print(error)
}

// To load the store HTML file:
myWKWebView.load(URLRequest(url: cachedHTMLURL)) // (file://.../tmp/my_html_content_string.html)

I had the same problem with WKWebView as it can not load both html strings and images at the same time for security purposes. I switched to UIWebView, which is deprecated, but I was able to load both html strings and referenced images at the same time.

I developed a definitive solution for the company I work for. But it relies on the html / javascript side. Anywhere inside your html code where you will reference to a local image <img src="..."/> you should set this "src" dynamically, and it will work seamlessly.

function getLocalURL(path) {
    let origin = window.location.origin
    if (origin == "file://") {
        return origin + window.location.pathname.replace("/index.html","") + path
    }
    return path
}

You should, clearly, rename index.html to whatever is your main .htm(l) filename :)

Usage:

getLocalURL("/local_images/location_icon.png")

Will return a WKWebView working path for the referenced local image path:

"file:///Users/arthurdapaz/Library/Developer/CoreSimulator/Devices/5073AF19-26A0-460E-BC82-E89100B8E1AB/data/Containers/Data/Application/2B099343-0BF5-4849-B1C2-2512377A9772/Documents/distDriver/local_images/location_icon.png"

Related