Download file from base64 url in android webview

Viewed 10434

I am writing a webview app in which i can download files from (html tag) urls to device. I can download files like png/jpg/pdf etc, but when url is a base64 string value i don't know how to download it. Can someone help me to achieve that?

For example, when the below html link clicked file abc.png can be downloaded easily

<a href="http://web.com/abc.png" download >Download</a>

But when url is base64 like below, webview can't download the "file":

<a href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIA..." download>Download</a>
3 Answers

I could manage to save base64 encoded data as a file. So, the basic short answer to my question was decoding encoded data to bytes and writing it to a file like this:

String base64EncodedString = encodedDataUrl.substring(encodedDataUrl.indexOf(",") + 1);
byte[] decodedBytes = Base64.decode(base64EncodedString, Base64.DEFAULT);
OutputStream os = new FileOutputStream(file);
os.write(decodedBytes);
os.close();

Just for reference for others who may come up with the same question I am adding my final code below. Inside onCreate() method i am handling file downloads like this:

webView.setDownloadListener(new DownloadListener() {
    @Override
    public void onDownloadStart(String url, String userAgent,
                                String contentDisposition, String mimeType,
                                long contentLength) {

        if (url.startsWith("data:")) {  //when url is base64 encoded data
            String path = createAndSaveFileFromBase64Url(url);
            return;
        }

        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(getResources().getString(R.string.msg_downloading));
        String filename = URLUtil.guessFileName(url, contentDisposition, mimeType);
        request.setTitle(filename);
        request.allowScanningByMediaScanner();
        request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
        request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, filename);
        DownloadManager dm = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
        dm.enqueue(request);
        Toast.makeText(getApplicationContext(), R.string.msg_downloading, Toast.LENGTH_LONG).show();
    }
});

And createAndSaveFileFromBase64Url() method which deals with base64 encoded data looks like this:

public String createAndSaveFileFromBase64Url(String url) {
        File path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
        String filetype = url.substring(url.indexOf("/") + 1, url.indexOf(";"));
        String filename = System.currentTimeMillis() + "." + filetype;
        File file = new File(path, filename);
        try {
            if(!path.exists())
                path.mkdirs();
            if(!file.exists())
                file.createNewFile();

            String base64EncodedString = url.substring(url.indexOf(",") + 1);
            byte[] decodedBytes = Base64.decode(base64EncodedString, Base64.DEFAULT);
            OutputStream os = new FileOutputStream(file);
            os.write(decodedBytes);
            os.close();

            //Tell the media scanner about the new file so that it is immediately available to the user.
            MediaScannerConnection.scanFile(this,
                    new String[]{file.toString()}, null,
                    new MediaScannerConnection.OnScanCompletedListener() {
                        public void onScanCompleted(String path, Uri uri) {
                            Log.i("ExternalStorage", "Scanned " + path + ":");
                            Log.i("ExternalStorage", "-> uri=" + uri);
                        }
                    });

            //Set notification after download complete and add "click to view" action to that
            String mimetype = url.substring(url.indexOf(":") + 1, url.indexOf("/"));
            Intent intent = new Intent();
            intent.setAction(android.content.Intent.ACTION_VIEW);
            intent.setDataAndType(Uri.fromFile(file), (mimetype + "/*"));
            PendingIntent pIntent = PendingIntent.getActivity(this, 0, intent, 0);

            Notification notification = new NotificationCompat.Builder(this)
                                                        .setSmallIcon(R.mipmap.ic_launcher)
                                                        .setContentText(getString(R.string.msg_file_downloaded))
                                                        .setContentTitle(filename)
                                                        .setContentIntent(pIntent)
                                                        .build();

            notification.flags |= Notification.FLAG_AUTO_CANCEL;
            int notificationId = 85851;
            NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
            notificationManager.notify(notificationId, notification);
        } catch (IOException e) {
            Log.w("ExternalStorage", "Error writing " + file, e);
            Toast.makeText(getApplicationContext(), R.string.error_downloading, Toast.LENGTH_LONG).show();
        }

        return file.toString();
    }

If you are using Java 1.8, you can try with

     import java.util.Base64;

     public class DecodeBase64 {

     public static void main(String []args){
        String encodedUrl = "aHR0cHM6Ly9zdGFja292ZXJmbG93LmNvbS9xdWVzdGlvbnMvNDY1NzkyMzcvZG93bmxvYWQtZmlsZS1mcm9tLWJhc2U2NC11cmwtaW4tYW5kcm9pZC13ZWJ2aWV3LzQ2NTc5MzE0";
        byte[] decodedBytes = Base64.getUrlDecoder().decode(encodedUrl);
        String result = new String(decodedBytes);
        System.out.println(result);
     }
}

output should be:

https://stackoverflow.com/questions/46579237/download-file-from-base64-url-in-android-webview/46579314

First of all you need to convert this base64 string to bitmap image format than try to download that.

you can convert your string like this.

public static Bitmap decodeBase64(String input)
{
    byte[] decodedByte = Base64.decode(input, Base64.DEFAULT); 


    return BitmapFactory.decodeByteArray(decodedByte, 0, decodedByte.length);
}

it will return bitmap of your base64.

Related