如何在wkwebview中下载文件 [英] How to download files in wkwebview

查看:63
本文介绍了如何在wkwebview中下载文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有人请告诉我如何在iOS wkwebview 中下载文件.我创建了一个 iOS webview 应用程序.在我加载的页面中,它有几个下载选项,但是当我点击下载时什么也没有发生.

Anybody please tell me how to download files in iOS wkwebview. I have created an iOS webview app. In the page I have loaded It has several download options but when I click download nothing happened.

注意:我不想创建额外的按钮来下载

Note: I dont want to create extra buttons to download

推荐答案

您也可以使用 JavaScript 下载您的文件,如 Sayooj 的链接 暗示.

You can also use JavaScript to download your file, as Sayooj's link implys.

当然,您将自己处理文件下载的代码.

Of cource, you will handle the file downloaded code yourself.

使用 func webView(_ webView: WKWebView, decisionPolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {,您将获得要下载的文件 url.

With func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {, you get the file url to download.

然后用JS下载.

JS调用一个下载的方法成功,你会收到通知 public func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {,

the JS call a downloaded method if success, you will be notified with public func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {,

然后你就可以处理你下载的文件了

Then you can handle your downloaded file

有点复杂.使用 JavaScript 下载文件,使用 WKScriptMessageHandler 在原生 Swift 和 JavaScript 之间进行通信.

class ViewController: UIViewController, WKUIDelegate, WKNavigationDelegate, WKScriptMessageHandler {  

    var webView: WKWebView!  
    let webViewConfiguration = WKWebViewConfiguration()  
    override func viewDidLoad() {  
        super.viewDidLoad()  

        // init this view controller to receive JavaScript callbacks  
        webViewConfiguration.userContentController.add(self, name: "openDocument")  
        webViewConfiguration.userContentController.add(self, name: "jsError")  
        webView = WKWebView(frame: yourFrame, configuration: webViewConfiguration)  
    }  

    func webView(_ webView: WKWebView,  
                 decidePolicyFor navigationAction: WKNavigationAction,  
                 decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {  
        let url = navigationAction.request.url  
        decisionHandler(.cancel)  
        executeDocumentDownloadScript(forAbsoluteUrl: url!.absoluteString)  

    }  

    /* 
     Handler method for JavaScript calls. 
     Receive JavaScript message with downloaded document 
     */  
    public func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {  
        debugPrint("did receive message \(message.name)")  


        if (message.name == "openDocument") {  
            handleDocument(messageBody: message.body as! String)  
        } else if (message.name == "jsError") {  
            debugPrint(message.body as! String)  
        }  
    }  

    /* 
     Open downloaded document in QuickLook preview 
     */  
    private func handleDocument(messageBody: String) {  
        // messageBody is in the format ;data:;base64,  

        // split on the first ";", to reveal the filename  
        let filenameSplits = messageBody.split(separator: ";", maxSplits: 1, omittingEmptySubsequences: false)  

        let filename = String(filenameSplits[0])  

        // split the remaining part on the first ",", to reveal the base64 data  
        let dataSplits = filenameSplits[1].split(separator: ",", maxSplits: 1, omittingEmptySubsequences: false)  

        let data = Data(base64Encoded: String(dataSplits[1]))  

        if (data == nil) {  
            debugPrint("Could not construct data from base64")  
            return  
        }  

        // store the file on disk (.removingPercentEncoding removes possible URL encoded characters like "%20" for blank)  
        let localFileURL = FileManager.default.temporaryDirectory.appendingPathComponent(filename.removingPercentEncoding ?? filename)  

        do {  
            try data!.write(to: localFileURL);  
        } catch {  
            debugPrint(error)  
            return  
        }  

        // and display it in QL  
        DispatchQueue.main.async {  
            // localFileURL  
            // now you have your file
        }  
    }  



    /* 
     Intercept the download of documents in webView, trigger the download in JavaScript and pass the binary file to JavaScript handler in Swift code 
     */  
    private func executeDocumentDownloadScript(forAbsoluteUrl absoluteUrl : String) {  
        // TODO: Add more supported mime-types for missing content-disposition headers  
        webView.evaluateJavaScript("""  
            (async function download() {  
                const url = '\(absoluteUrl)';  
                try {  
                    // we use a second try block here to have more detailed error information  
                    // because of the nature of JS the outer try-catch doesn't know anything where the error happended  
                    let res;  
                    try {  
                        res = await fetch(url, {  
                            credentials: 'include'  
                        });  
                    } catch (err) {  
                        window.webkit.messageHandlers.jsError.postMessage(`fetch threw, error: ${err}, url: ${url}`);  
                        return;  
                    }  
                    if (!res.ok) {  
                        window.webkit.messageHandlers.jsError.postMessage(`Response status was not ok, status: ${res.status}, url: ${url}`);  
                        return;  
                    }  
                    const contentDisp = res.headers.get('content-disposition');  
                    if (contentDisp) {  
                        const match = contentDisp.match(/(^;|)\\s*filename=\\s*(\"([^\"]*)\"|([^;\\s]*))\\s*(;|$)/i);  
                        if (match) {  
                            filename = match[3] || match[4];  
                        } else {  
                            // TODO: we could here guess the filename from the mime-type (e.g. unnamed.pdf for pdfs, or unnamed.tiff for tiffs)  
                            window.webkit.messageHandlers.jsError.postMessage(`content-disposition header could not be matched against regex, content-disposition: ${contentDisp} url: ${url}`);  
                        }  
                    } else {  
                        window.webkit.messageHandlers.jsError.postMessage(`content-disposition header missing, url: ${url}`);  
                        return;  
                    }  
                    if (!filename) {  
                        const contentType = res.headers.get('content-type');  
                        if (contentType) {  
                            if (contentType.indexOf('application/json') === 0) {  
                                filename = 'unnamed.pdf';  
                            } else if (contentType.indexOf('image/tiff') === 0) {  
                                filename = 'unnamed.tiff';  
                            }  
                        }  
                    }  
                    if (!filename) {  
                        window.webkit.messageHandlers.jsError.postMessage(`Could not determine filename from content-disposition nor content-type, content-dispositon: ${contentDispositon}, content-type: ${contentType}, url: ${url}`);  
                    }  
                    let data;  
                    try {  
                        data = await res.blob();  
                    } catch (err) {  
                        window.webkit.messageHandlers.jsError.postMessage(`res.blob() threw, error: ${err}, url: ${url}`);  
                        return;  
                    }  
                    const fr = new FileReader();  
                    fr.onload = () => {  
                        window.webkit.messageHandlers.openDocument.postMessage(`${filename};${fr.result}`)  
                    };  
                    fr.addEventListener('error', (err) => {  
                        window.webkit.messageHandlers.jsError.postMessage(`FileReader threw, error: ${err}`)  
                    })  
                    fr.readAsDataURL(data);  
                } catch (err) {  
                    // TODO: better log the error, currently only TypeError: Type error  
                    window.webkit.messageHandlers.jsError.postMessage(`JSError while downloading document, url: ${url}, err: ${err}`)  
                }  
            })();  
            // null is needed here as this eval returns the last statement and we can't return a promise  
            null;  
        """) { (result, err) in  
            if (err != nil) {  
                debugPrint("JS ERR: \(String(describing: err))")  
            }  
        }  
    }  
}  

这篇关于如何在wkwebview中下载文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆