Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

I'm showing html page in a WKWebView . My html contains links with embedded pdf as follow:

<td><div class="truncate"><a id="allegato1" class="link" href="data:octet-stream;base64,JVBERi0xLjIgCiXi48/
.........................................................
Ao3OTA2MiAKJSVFT0YgCg==%0A" download="FATCLI_19244324.PDF">FATCLI_19244324.PDF</a></div></td>

Now, I have to intercept click in the above links, save pdf on disk and then open the file with a reader. I'm able to do this as follow:

func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Swift.Void) {
    if navigationAction.navigationType == .linkActivated, let url = navigationAction.request.url  {
        if url.scheme == "data" {
            let splitted = url.absoluteString.components(separatedBy: "base64,")
            if splitted.count == 2 {
                let documentName = .... // What should I do?
                if let data = Data(base64Encoded: splitted[1]) {
                    let fileURL = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(documentName)
                        try data.write(to: fileURL, options: .atomicWrite)
                        // Show pdf with via UIDocumentInteractionController
                        decisionHandler(.cancel)
                        return
                    } catch {
                        // Manage the error
                        decisionHandler(.cancel)
                        return
        decisionHandler(.allow)
    } else {
        decisionHandler(.allow)

What I am trying to do is find a way to read document name from element download or from tag a value (FATCLI_19244324.PDF in this case). But it seems to be no way to do this in webView(_:decidePolicyFor:decisionHandler:)method.

Can anyone help me?

I solved my problem by injecting some javascript in my WKWebView.

override func viewDidLoad() {
    super.viewDidLoad()
    let configuration = WKWebViewConfiguration()
    let userController:WKUserContentController = WKUserContentController()
    userController.add(self, name: "linkClicked")
    let js:String = """
                    var links = document.getElementsByClassName("link");
                    Array.prototype.forEach.call(links, function(link) {
                    // Disable long press
                    link.style.webkitTouchCallout='none';
                    link.addEventListener("click", function() {
                    var messageToPost = {'download': link.getAttribute("download"), 'href': link.getAttribute("href")};                  window.webkit.messageHandlers.linkClicked.postMessage(messageToPost);
                    },false);
    let userScript:WKUserScript =  WKUserScript(source: js, injectionTime: .atDocumentEnd, forMainFrameOnly: false)
    userController.addUserScript(userScript)
    WKUserContentController
    configuration.userContentController = userController;
    myWebView = WKWebView(frame: webViewContainer.bounds, configuration: configuration)
    ......

In this way I can read download and href elements in userContentController(_:didReceive:) method and save pdf on disk with right name.

func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
    guard let body = message.body as? [String: Any] else { return }
    guard let documentName = body["download"] as? String, let href = body["href"] as? String, let url = URL(string: href) else { return }
    if url.scheme == "data" {
        let splitted = url.absoluteString.components(separatedBy: "base64,")
        if splitted.count == 2 {
            if let data = Data(base64Encoded: splitted[1]) {
                let fileURL = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(documentName)
                    try data.write(to: fileURL, options: .atomicWrite)
                    // Show pdf with via UIDocumentInteractionController
                } catch {
                    // Manage the error
        

Thanks for contributing an answer to Stack Overflow!

  • Please be sure to answer the question. Provide details and share your research!

But avoid

  • Asking for help, clarification, or responding to other answers.
  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.