首页 > 解决方案 > Android WebView - 不能从 WebView 下载文件

问题描述

我使用这个下载监听器

mWebView.setDownloadListener(new DownloadListener() {
        @Override
        public void onDownloadStart(String url, String userAgent, String contentDescription,
                                    String mimetype, long contentLength) {
            DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url));
            request.allowScanningByMediaScanner();
            request.setNotificationVisibility(
                    DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
            String fileName = URLUtil.guessFileName(url,contentDescription,mimetype);
            request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS,fileName);
            DownloadManager dManager = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
            dManager.enqueue(request);
        }
    });

但是不要在我需要的网站上工作。如果我使用例如这个 url

https://www.sendspace.com/....

文件正常下载。

但如果我使用这个网址

http://m.slovakrail.sk

我买了票,在最后一个网站上我点击下载按钮,但下载不起作用。来自网站的按钮代码是

<input type="submit" name="j_idt91:j_idt93:0:j_idt94" value="Stiahnuť cestovný doklad" class="btn" />

谢谢你的回复。

标签: android

解决方案


我假设下载表单使用 POST。我发现这样做的唯一方法是使用 注入 JavaScript 代码webView.loadUrl("javascript:..."),它会从表单中提取所有需要的信息。然后手动执行 POST 请求以下载文件。(例如使用 OkHttp。)

要让DownloadManager知道下载的文件,您可以使用该downloadManager.addCompletedDownload(...)方法。


示例代码 (Kotlin)

webView.loadUrl("""
    javascript:(function () {
        let form = document.querySelector("#form-id");
        let inputs = [...form.querySelectorAll("input[type='hidden']")];
        form.querySelector("button.pdfLink[type='submit']").addEventListener(
            'click',
            (e) => {
                e.stopPropagation();
                e.preventDefault();
                App.download(JSON.stringify({
                    method: form.method,
                    url: form.action,
                    fields: inputs.map(f => ({key: f.name, value: f.value}))
                }));
            },
            false);
    })()
    """.trimIndent())

您还需要将 JS 接口添加到WebView.

webView.addJavascriptInterface(adapter, "App")

WebViewJS 适配器可能如下所示:

class WebViewJsAdapter {
    @JavascriptInterface
    fun download(formData: String) {
        val data = JSONObject(formData)
        // 1. download the file
        ...
        // 2. add the downloaded file to the DownloadManager
        //    using `downloadManager.addCompletedDownload(...)`
        ...
    }
}

推荐阅读