1

I have a HTML file which contains local resource files such as css, js files inside its content. These local resource files are in zip format. My app use WKWebView to display this html file. I m trying to upload an image in one of the html image element on WKWebview which is saved locally and html is not updated with the image. I have a html image tag in local html like this.

<img id='image' style='display: block; height: 100%; width:100%; margin:0 auto;' />

And this image to load in this image tag is generated after the local html file is loaded in the WKWebview. Once the image is generated, I am trying to update the image tag with the evaluate javascript method like this.

NSString *js = @"document.getElementById('image').src='document directory/Library/images/generatedImage.png';"
[self.wkWebView evaluateJavaScript:js completionHandler:nil];

Am I doing something wrong here. I also read that we can't update the image locally which was 2 years ago, still the same? Is there any workaround solution for my scenario. Thanks in advance.

nOOb iOS
  • 1,384
  • 2
  • 19
  • 37
  • Check out this question, maybe it helps: https://stackoverflow.com/questions/59928683/ios-wkwebview-how-to-allow-html-file-located-in-bundle-read-access-to-documents – ndreisg Aug 18 '20 at 09:25

2 Answers2

3

I can think of two ways to do what you want.

  1. Custom URL Scheme
  2. Convert the image to base64 then set it via evaluate Javascript

Custom URL Scheme

This is supported from iOS Version 11, if you are supporting version below 11 then you are better off with second approach. The basic idea is mention your URL with custom protocol like my-scheme://your-path then intercept that path and provide the response to WKWebView. In this you have to create a class that extends WKSchemeHandler and override it's required methods. e.g.

import WebKit
import Foundation
class CustomeSchemeHandler : NSObject,WKURLSchemeHandler {
    func webView(_ webView: WKWebView, start urlSchemeTask: WKURLSchemeTask) {
       
        
    }

    func webView(_ webView: WKWebView, stop urlSchemeTask: WKURLSchemeTask) {
       
    }
}

In the start method you can load the content from your desired source and then return the response via

urlSchemeTask.didReceive(response)
urlSchemeTask.didReceive(data)
urlSchemeTask.didFinish()

After implementing your logic, you need to register it with WKWebView via setURLSchemeHandler(_:forURLScheme:)

After seeing the above you can mention image URL with your custom scheme and leave the work to your CustomSchemeHandler.

This approach is very mature and can be really helpful in the long run. I found a very good and brief article that covers the implementation in details, do check it out: https://medium.com/@kumarreddy_b/custom-scheme-handling-in-uiwebview-wkwebview-bbeb2f3f6cc1

Convert the image to base64 then set it via evaluating Javascript

  1. Create UIImage from your path e.g. https://stackoverflow.com/a/43006566/2299040
  2. Convert the image to base64
  3. Get the Id of your HTML image element and load the base64 String

e.g.

if let image = UIImage(contentsOfFile: ""){
    //Now use image to create into NSData format
    if let imageData = image.jpegData(compressionQuality: 0.8){
        let strBase64 = imageData.base64EncodedString(options: .lineLength64Characters)
        webView.evaluateJavaScript("document.getElementById('your-image-element-id').setAttribute('src', '\(strBase64)');")
    }
}
Sahil Manchanda
  • 9,812
  • 4
  • 39
  • 89
  • I used 2nd method. Converted the image into Base64 and then added via javascript. Thanks for your help. – nOOb iOS Aug 21 '20 at 09:59
  • It stopped working on iOS14. So, thought of implementing WKURLSchemeHandler. The delegate is called when webview loads but when I am trying to add source of image tag using evaluate javascript it doesn't get called. – nOOb iOS Feb 09 '21 at 18:58
0

For your example, I was able to load an image from the internet by setting that URL as the src.

I guess you might have not given read access to your local image file directory while loading the webview.

Utilize loadFileURL method of wkwebview to load an HTML file by giving access to a particular directory

For EG (in Swift),

let imgDir = "<your image directory>"
let imgDirUrl = URL(fileURLWithPath: String(format: "%@", imgDir), isDirectory: true)
webView.loadFileURL(<your HTML file URL path>, allowingReadAccessTo: imgDirUrl)

(In objc)

NSString *imgDir = "<your image directory>"
NSURL *imgDirUrl = [NSURL fileURLWithPath:[NSString stringWithFormat:@"%@",imgDir] isDirectory:true];
[webView loadFileURL:<your HTML file URL path> allowingReadAccessToURL:imgDirUrl];
Swami Nathan
  • 411
  • 2
  • 8
  • The image is created on the fly and saved in different path other than html file url path. Is there any other way to update the image using javascript on the html? – nOOb iOS Aug 12 '20 at 09:10
  • Can you try giving read permission to the whole documents directory? In that case the image can be accessed wherever it is created – Swami Nathan Aug 12 '20 at 09:35
  • The html is loaded via Cordova WebviewEngine and I tried giving access to folders in their WKConfiguration preferences and it doesnt seem to work. – nOOb iOS Aug 12 '20 at 10:36
  • Can you share the code where you are loading the webview? – Swami Nathan Aug 12 '20 at 10:51