【问题标题】:Android WebView: Download when content-type is application/pdf and render web page if notAndroid WebView:当内容类型为 application/pdf 时下载,如果不是则呈现网页
【发布时间】:2015-05-27 10:00:07
【问题描述】:

我有一个特定的场景,我发出一个 POST 请求,并在正文中使用一个唯一的票证来取回结果页面。

结果页面是Content-Typeapplication/pdftext/html。 票证只有一次有效,所以页面只能加载一次。

问题是 Android WebView 不支持 pdf 的呈现(与 iOS 上的等价物一样)。

我尝试了以下方法:

  1. 使用主要请求检查 http 响应标头,然后使用第二个请求下载文件(如果它是 pdf)并在 PDF 应用程序中打开它(有效)。但是对于加载 html 页面,第二个请求失败,因为票证不再有效。

  2. 同时下载pdf和html页面,然后在本地的pdf app/WebView中打开。这有效,网页中的两个相对链接都被破坏了。有没有好办法下载它们?

x。是否可以中断 WebView 中的请求以读取响应标头并触发下载,如果它是 pdf 则继续渲染?找不到一个好的答案。

【问题讨论】:

    标签: android html pdf webview http-headers


    【解决方案1】:

    您可以使用内置方法 URLConnection.getContentType() 来达到确切目的。获得内容类型后,继续下载或传递给WebView

    进口:

    import java.net.URL;
    import java.net.URLConnection;
    import java.io.IOException;
    import java.util.concurrent.ExecutionException;
    

    这是一个在加载前拦截 URL 的示例:

    webView.setWebViewClient(new WebViewClient() {
                @Override
                public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
                    String requestedUrl = request.getUrl().toString();
    
                    boolean isDownloadableFile = false;
    
                    try {
                        isDownloadableFile = new FetchContentTypeAsync(requestedUrl).execute().get();
                    } catch (ExecutionException e) {
                        e.printStackTrace();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
    
                    // downloadable file / dont load it in webview
                    if (isDownloadableFile) {
                        // download the file here
                        return false;
                    } else {
                        // non downloadable file / load it in webview
                        view.loadUrl(requestedUrl);
                        return super.shouldOverrideUrlLoading(view, request);
                    }
                }
            });
    

    FetchContentTypeAsync 用于在后台运行任务

    private static class FetchContentTypeAsync extends AsyncTask<Void, Void, Boolean> {
    
            private String requestedUrl;
    
            FetchContentTypeAsync(String requestedUrl) {
                this.requestedUrl = requestedUrl;
            }
    
            @Override
            protected Boolean doInBackground(Void... voids) {
                boolean isDownloadableFile = false;
                try {
                    URL url = new URL(requestedUrl);
                    URLConnection urlConnection = url.openConnection();
                    String contentType = urlConnection.getContentType();
                    isDownloadableFile = contentType.equalsIgnoreCase("application/pdf");
                } catch (IOException e) {
                    e.printStackTrace();
                }
                return isDownloadableFile;
            }
        }
    

    下载文件检查 Download a file with Android, and showing the progress in a ProgressDialog

    【讨论】:

    • 它是用 Kotlin 编写的。您需要 Java 版本的代码吗?
    • 哦,好的,我明白了。是的,我正在使用 Java。
    • 最好同时提供这两种解决方案,以防其他人使用 Kotlin。
    • WebView 默认不支持 pdf 文件。您需要使用 3rd 方库打开它或使用 Google 文档通过 mWebView.loadUrl("docs.google.com/gview?embedded=true&url="+ webUrl); 加载它
    • 我的荣幸。 Google 使用网络“gview”来呈现 pdf,并且不会永久存储您的文件。但是,在这种情况下,打开具有安全问题的文档可能并不理想。
    【解决方案2】:

    设置 WebViewClient 后,它有一些接口来拦截请求,最广泛使用的是 shouldOverrideUrlLoading(),但您也可以覆盖 shouldInterceptRequest() 并在那里拦截它。

    webView.setWebViewClient(new WebViewClient() {
        @Override public boolean shouldOverrideUrlLoading(WebView view, String url) {
            // Check the URL here - if it is a file, 
            // then initiate the download
            return false;
        }
    }
    

    【讨论】:

    • 如果 URL 中没有文件扩展名怎么办?
    猜你喜欢
    • 1970-01-01
    • 2018-07-15
    • 2018-05-18
    • 2014-01-05
    • 2019-09-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多