在WebView中下载文件

102

我在我的Android应用程序中有一个webview。当用户进入webview并单击下载文件的链接时,什么都不会发生。

URL = "my url";
mWebView = (WebView) findViewById(R.id.webview);
mWebView.setWebViewClient(new HelloWebViewClient());
mWebView.getSettings().setDefaultZoom(ZoomDensity.FAR);
mWebView.loadUrl(URL);
Log.v("TheURL", URL);

如何在webview中启用下载?如果我禁用webview并启用从应用程序加载URL的意图,则下载可以无缝运行。

String url = "my url";
Intent i = new Intent(Intent.ACTION_VIEW);
i.setData(Uri.parse(url));
startActivity(i);

有人可以帮我吗?页面可以正常加载,但是HTML页面中指向图像文件的链接无法使用...


1
您可以使用此Webview子类,它会自动处理下载等操作:https://github.com/delight-im/Android-AdvancedWebView - caw
6个回答

150

你尝试过了吗?

mWebView.setDownloadListener(new DownloadListener() {
    public void onDownloadStart(String url, String userAgent,
                String contentDisposition, String mimetype,
                long contentLength) {
        Intent i = new Intent(Intent.ACTION_VIEW);
        i.setData(Uri.parse(url));
        startActivity(i);
    }
});

示例链接:Webview文件下载 - 感谢@c49


3
这段代码可以工作,但是如果用户在WebView中进行了身份验证,一旦Android浏览器启动,他们将被要求再次登录,之后才会发生下载。我正在尝试找到一种避免这种情况的方法,以便他们无需再次登录即可进行下载。 - MetaGuru
1
尝试使用此链接进行任何类型的下载:http://androidtrainningcenter.blogspot.in/2013/11/download-file-videoaudiotext-through.html - Tofeeq Ahmad
1
@ioSamurai,你找到了下载需要用户身份验证的文件的方法吗?当不需要用户认证时, webView.setDownloadListener() 功能完美。但是,当我从Google Drive或其他需要用户认证的来源下载文件时,虽然会下载一个文件,但是里面没有数据。@user370305您也可以提供帮助。 - Sp4Rx
1
@Sp4Rx 是的,它在那上面可以工作,但我需要一些只能在 WebView 上工作的其他功能。 - Rohit
1
@user370305 我应该把这段代码放在哪里?我正在使用React Native。 - Laney Williams
显示剩余2条评论

71

试一下这个。在浏览了许多帖子和论坛后,我发现了这个。

mWebView.setDownloadListener(new DownloadListener() {       

    @Override
    public void onDownloadStart(String url, String userAgent,
                                    String contentDisposition, String mimetype,
                                    long contentLength) {
            DownloadManager.Request request = new DownloadManager.Request(
                    Uri.parse(url));

            request.allowScanningByMediaScanner();
            request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED); //Notify client once download is completed!
            request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, "Name of your downloadble file goes here, example: Mathematics II ");
            DownloadManager dm = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
            dm.enqueue(request);
            Toast.makeText(getApplicationContext(), "Downloading File", //To notify the Client that the file is being downloaded
                    Toast.LENGTH_LONG).show();

        }
    });

不要忘记授予权限!这非常重要!将其添加到您的清单文件(AndroidManifest.xml文件)中

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />        <!-- for your file, say a pdf to work -->

希望这能有所帮助。 祝好 :)


18
谢谢,它起作用了!为了使用原始文件名,我们可以使用:final String filename= URLUtil.guessFileName(url, contentDisposition, mimetype); - Jawaad
10
@SaiZ,你的例子包含了一些与未使用的意图有关的代码,我想你应该将其移除。 - j.c
1
@j.c 我已经移除了未使用的代码,感谢你的反馈 ;) - MatPag
3
这是完美的答案,它将直接从 webview 启动下载,这正是预期的...谢谢。 - Ghanshyam Bagul
1
@Jawaad 感谢您的回复。然而我还是毫无头绪。我甚至不知道要打开哪个文件。我尝试在整个解决方案中搜索 request.setDestinationInExternalPublicDir 但是没有匹配项。#xamarin-forms - s3c
显示剩余2条评论

30
    mwebView.setDownloadListener(new DownloadListener()
   {

  @Override  


   public void onDownloadStart(String url, String userAgent,
        String contentDisposition, String mimeType,
        long contentLength) {

    DownloadManager.Request request = new DownloadManager.Request(
            Uri.parse(url));


    request.setMimeType(mimeType);


    String cookies = CookieManager.getInstance().getCookie(url);


    request.addRequestHeader("cookie", cookies);


    request.addRequestHeader("User-Agent", userAgent);


    request.setDescription("Downloading file...");


    request.setTitle(URLUtil.guessFileName(url, contentDisposition,
            mimeType));


    request.allowScanningByMediaScanner();


    request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
    request.setDestinationInExternalPublicDir(
            Environment.DIRECTORY_DOWNLOADS, URLUtil.guessFileName(
                    url, contentDisposition, mimeType));
    DownloadManager dm = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
    dm.enqueue(request);
    Toast.makeText(getApplicationContext(), "Downloading File",
            Toast.LENGTH_LONG).show();
}});

1
请解释你所写的内容,仅有代码是不够的。 - Saveen
2
设置Cookie拯救了我的一天!谢谢! - francisco_ssb
这个应该被接受了,可以工作。谢谢伙计。 - Surya Reddy
我正在使用Web视图从Digi-locker下载文档,但是使用相同的代码片段下载失败。文件格式为PDF。有人能帮我吗? - Ashish Patel

17

尝试使用下载管理器,它可以帮助您下载所有您想要的内容并节省时间。

请检查以下选项:

选项1 ->

 mWebView.setDownloadListener(new DownloadListener() {
        public void onDownloadStart(String url, String userAgent,
                String contentDisposition, String mimetype,
                long contentLength) {
 Request request = new Request(
                            Uri.parse(url));
                    request.allowScanningByMediaScanner();
                    request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
                    request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, "download"); 
                    DownloadManager dm = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
                    dm.enqueue(request);        

        }
    });

选项2 ->

if(mWebview.getUrl().contains(".mp3") {
 Request request = new Request(
                        Uri.parse(url));
                request.allowScanningByMediaScanner();
                request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
                request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, "download"); 
// You can change the name of the downloads, by changing "download" to everything you want, such as the mWebview title...
                DownloadManager dm = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
                dm.enqueue(request);        

    }

6
webView.setDownloadListener(new DownloadListener()
        {
            @Override
            public void onDownloadStart(String url, String userAgent,
                                        String contentDisposition, String mimeType,
                                        long contentLength) {
                DownloadManager.Request request = new DownloadManager.Request(
                        Uri.parse(url));
                request.setMimeType(mimeType);
                String cookies = CookieManager.getInstance().getCookie(url);
                request.addRequestHeader("cookie", cookies);
                request.addRequestHeader("User-Agent", userAgent);
                request.setDescription("Downloading File...");
                request.setTitle(URLUtil.guessFileName(url, contentDisposition, mimeType));
                request.allowScanningByMediaScanner();
                request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
                request.setDestinationInExternalPublicDir(
                        Environment.DIRECTORY_DOWNLOADS, URLUtil.guessFileName(
                                url, contentDisposition, mimeType));
                DownloadManager dm = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
                dm.enqueue(request);
                Toast.makeText(getApplicationContext(), "Downloading File", Toast.LENGTH_LONG).show();
            }});

2
如果您不想使用下载管理器,则可以使用此代码。
webView.setDownloadListener(new DownloadListener() {

            @Override
            public void onDownloadStart(String url, String userAgent, String contentDisposition
                    , String mimetype, long contentLength) {

                String fileName = URLUtil.guessFileName(url, contentDisposition, mimetype);

                try {
                    String address = Environment.getExternalStorageDirectory().getAbsolutePath() + "/"
                            + Environment.DIRECTORY_DOWNLOADS + "/" +
                            fileName;
                    File file = new File(address);
                    boolean a = file.createNewFile();

                    URL link = new URL(url);
                    downloadFile(link, address);

                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });

 public void downloadFile(URL url, String outputFileName) throws IOException {

        try (InputStream in = url.openStream();
             ReadableByteChannel rbc = Channels.newChannel(in);
             FileOutputStream fos = new FileOutputStream(outputFileName)) {
            fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
        }
           // do your work here

    }

这将在手机存储中的下载文件夹中下载文件。如果您想在后台下载,请使用线程(使用thread.alive()和timer类来知道下载是否完成)。当我们下载小文件时,这非常有用,因为您可以在下载后立即执行下一个任务。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接