Download the file with blob URL in Android WebView


What is the Blob URL?

Blob URLs can only be generated by the browser with use of internal mapping and used within the current document while it’s open which means it is valid for the same session (ie. the life of the page/document). The blob URL looks like this:

blob:http://example.com/550e8400-e29b-41d4-a716-446655440000

Below is the sample HTML code that generates blob:

<!DOCTYPE html>
<html>
<head>
	<title>JavaScript Blob Example</title>
</head>
<body>
	<a download="demo.txt" href='#'
		id="link">Download sample text file</a>
	<script>
		let abc = new Blob(["This is demo file."],{ type: 'text/plain' });
		link.href = URL.createObjectURL(abc);
	</script>
</body>
</html>

To download files having Blob URLs inside Android:

Add a custom Javascript Interface to WebView using the below method. After adding this, we will be able to call Android methods from JavaScript code:

addJavascriptInterface(new MyJavascriptInterface(),"Android");

Then, we need to load the blob URL from our WebView class:

loadUrl(MyJavascriptInterface.getBase64StringFromBlobUrl(url));

We need to use JavaScript code inside WebView’s JavascriptInterface to convert the blob URL to base64, as shown below:

public static String getBase64StringFromBlobUrl(String blobUrl, String mimetype)
{
var xhr = new XMLHttpRequest();
xhr.open('GET', 'blobUrl', true);
xhr.setRequestHeader('Content-type','text/plain');
xhr.responseType = 'blob';
xhr.onload = function(e) {
    if (this.status == 200) {
        var blobPdf = this.response;
        var reader = new FileReader();
        reader.readAsDataURL(blobPdf);
        reader.onloadend = function() {
            base64data = reader.result;}
window.Android.convertBase64StringToFileAndStoreIt
(base64data,'text/plain');
}

After getting the base64 string, we need to call the android function convertBase64StringToFileAndStoreIt() from the above JavaScript and from that function we can decode it into a file. Below is the function that needs to be added in MyJavascriptInterface class to convert the base64 string to a file and store it in Device storage:

@android.webkit.JavascriptInterface
public void convertBase64StringToFileAndStoreIt(String base64PDf, String mimetype) throws IOException {
   BufferedOutputStream output = null;


   // create file inside device storage
   String currentDateTime = DateFormat.getDateTimeInstance().format(new Date());
   String newTime = currentDateTime.replaceFirst(", ","_").replaceAll(" ","_").replaceAll(":","-");
   MimeTypeMap mimeTypeMap = MimeTypeMap.getSingleton();
   String extension = mimeTypeMap.getExtensionFromMimeType(mimetype);
   final File dwldsPath = new File(Environment.getExternalStoragePublicDirectory(
           Environment.DIRECTORY_DOWNLOADS) + "/" + newTime + "_." + extension);


// convert base64 string to readable content and store it in file
   String source = URLDecoder.decode(base64PDf).replaceAll("data:.+?,","");
     if(extension.equalsIgnoreCase("txt") && base64PDf.contains("base64")) {
       byte[] pdfAsBytes = Base64.decode(source, 0);
       try(FileOutputStream os = new FileOutputStream(dwldsPath, false)){
           os.write(pdfAsBytes);
           os.flush();
       }
       catch (Exception e){ Log.e("Error",e.toString());}
   }
   else {
       output = new BufferedOutputStream(new FileOutputStream(dwldsPath));
       output.write(source.getBytes());
       output.flush();
   }
}

Leave A Comment

Your email address will not be published. Required fields are marked *