Download file inside WebView
Asked Answered
I

6

104

I have a webview in my Android Application. When user goes to webview and click a link to download a file nothing happens.

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);

How to enable download inside a webview? If I disable webview and enable the intent to load the URL on browser from application then download works seamlessly.

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

Can someone help me out here? The page loads without issue but the link to a image file in the HTML page is not working...

Initiatory answered 9/4, 2012 at 4:56 Comment(1)
You may use this Webview subclass which handles downloads etc. automatically: github.com/delight-im/Android-AdvancedWebViewBeset
P
150

Have you tried?

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);
    }
});

Example Link: Webview File Download - Thanks @c49

Paramaribo answered 9/4, 2012 at 5:25 Comment(7)
This code works, but if the user was authenticated in the WebView they are asked to log in again once the Android browser launches, after that the download happens. I'm trying to find a way to avoid that, so the download happens without them having to log in again.Enameling
Try this link for any kind of download androidtrainningcenter.blogspot.in/2013/11/…Outrageous
@ioSamurai Have you found a way to download files which requires user authentication. webView.setDownloadListener() works perfectly when there is no user auth required. But when I download a file from google drive or other sources which requires user auth, a file is downloaded but there is no data. @Paramaribo you can also help.Heeled
You can check Chrome Custom tabs which will solve most of the problems. @RohitHeeled
@Heeled yeah it works on that but I need some other functionality that only works on webviewPenutian
@Paramaribo Where would I insert this code? I am using React Native.Prophecy
I like the simplicity of this method and with a dynamically created PDF file it works very well for me, but the process opens a browser and leave it on top of my application; is it possible to run the same code, but without the browser being left open?Caesalpiniaceous
A
72

Try this out. After going through a lot of posts and forums, I found this.

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();

        }
    });

Do not forget to give this permission! This is very important! Add this in your Manifest file(The AndroidManifest.xml file)

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

Hope this helps. Cheers :)

Amanuensis answered 30/6, 2015 at 2:58 Comment(7)
Thanks it worked!, for using original file name, we can use: final String filename= URLUtil.guessFileName(url, contentDisposition, mimetype);Lois
@SaiZ your example contains some code about an unused intent, i guess you should remove it.Hanschen
@Hanschen i removed the unused code, thanks for reporting it ;)Aluin
This is perfect answer this would launch download from webview directly, which is actually expected... ThanksFission
@Lois Could you please explain where should I put this native android code? I work with Xamarin.forms which compiles to native and I usually dare not touch native code, but here it's a must. TYIA.Poul
@s3c, You can put it right above the request.setDestinationInExternalPublicDir And replace "Name of your downloadble file goes here, example: Mathematics II " with filenameLois
@Lois Thank you for your response. I'm still clueless though. I don't even know which file to open. I tried searching my entire solution for request.setDestinationInExternalPublicDir but there were no matches. #xamarin-formsPoul
Q
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();
}});
Quiroz answered 31/12, 2016 at 15:54 Comment(4)
please explain what you wrote. just code is not enoughUnfortunate
Setting cookies saved my day! Thanks!Guess
this should be accepted answer, works . thank you buddyKnowhow
i am downloading document from Digi-locker using web view, but it's getting download unsuccessful using same code snippet. the file format is pdf. can anyone help me out.Tractate
M
17

Try using download manager, which can help you download everything you want and save you time.

Check those to options:

Option 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);        

        }
    });

Option 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);        

    }
Muscolo answered 5/8, 2014 at 8:9 Comment(0)
L
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();
            }});
Liquidity answered 25/11, 2020 at 11:23 Comment(0)
L
2

If you don't want to use a download manager then you can use this code

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

    }

This will download files in the downloads folder in phone storage. You can use threads if you want to download that in the background (use thread.alive() and timer class to know the download is complete or not). This is useful when we download small files, as you can do the next task just after the download.

Lid answered 10/12, 2020 at 20:28 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.