4

I want to download the file from webview but getting error every time that ( can only download HTTP/HTTPS URIs: blob:https://..)

I'm using this in my code:

ngOnInit() {
        let webview: WebView = this.webViewRef.nativeElement;

        if (isAndroid) {

            webview.on(WebView.loadStartedEvent, function () {
                webview.android.getSettings().setBuiltInZoomControls(false);
                webview.android.getSettings().setJavaScriptEnabled(true);
                webview.android.getSettings().setJavaScriptCanOpenWindowsAutomatically(true);
                webview.android.getSettings().setAllowFileAccess(true);
                webview.android.getSettings().setPluginsEnabled(true);
                webview.android.getSettings().setAllowContentAccess(true);
                webview.android.getSettings().setAllowFileAccess(true);
                webview.android.getSettings().setAllowFileAccessFromFileURLs(true);
                webview.android.getSettings().setAllowUniversalAccessFromFileURLs(true);
                webview.android.getSettings().setDomStorageEnabled(true);
                webview.android.getSettings().setDefaultTextEncodingName("utf-8");

                webview.android.setDownloadListener(new android.webkit.DownloadListener({
                    onDownloadStart(url, userAgent, contentDisposition, mimetype, contentLength) {
                        let request = new android.app.DownloadManager.Request(android.net.Uri.parse(url));
                        request.setMimeType(mimetype);
                        let cookies = android.webkit.CookieManager.getInstance().getCookie(url);
                        request.addRequestHeader("cookie", cookies);
                        request.addRequestHeader("User-Agent", userAgent);
                        request.setDescription("Downloading file...");
                        request.setTitle(android.webkit.URLUtil.guessFileName(url, contentDisposition, mimetype));
                        request.allowScanningByMediaScanner();
                        request.setNotificationVisibility(android.app.DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
                        request.setDestinationInExternalPublicDir(android.os.Environment.DIRECTORY_DOWNLOADS, android.webkit.URLUtil.guessFileName(url, contentDisposition, mimetype));
                        let dm = utils.ad.getApplicationContext().getSystemService(android.content.Context.DOWNLOAD_SERVICE);
                        dm.enqueue(request);
                    }
                }));
            });
        }

please help me in this. Thanks

  • Can you try printing what exactly it gives in URL, make sure it does not have any extra spaces or unwanted characters. – Manoj Dec 06 '18 at 08:55
  • it doesn't have white spaces, this error comes due to blob type i think –  Dec 06 '18 at 09:57
  • When the error is about URL, do you think you can at least share what is the URL you are passing for download. – Manoj Dec 06 '18 at 10:00
  • I'm downloading different files. It is something like this ---> blob:https://xyz.../b53... there is some restriction put https after blob –  Dec 06 '18 at 10:10

2 Answers2

5

Blob url contains url in Encoded format so You have to first convert url to Base64 and then store data in file. For that you need to use JavascriptInterface

public class JavaScriptInterface {
private Context context;
    private NotificationManager nm;
    public JavaScriptInterface(Context context) {
        this.context = context;
    }

    @JavascriptInterface
    public void getBase64FromBlobData(String base64Data) throws IOException {
        convertBase64StringToPdfAndStoreIt(base64Data);
    }
    public static String getBase64StringFromBlobUrl(String blobUrl){
        if(blobUrl.startsWith("blob")){

            return "javascript: var xhr=new XMLHttpRequest();" +
                    "xhr.open('GET', '"+blobUrl+"', true);" +
                    "xhr.setRequestHeader('Content-type','application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=UTF-8');" +
                    "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;" +
                    "            Android.getBase64FromBlobData(base64data);" +
                    "        }" +
                    "    }" +
                    "};" +
                    "xhr.send();";


        }
        return "javascript: console.log('It is not a Blob URL');";
    }
    private void convertBase64StringToPdfAndStoreIt(String base64PDf) throws IOException {

        Log.e("base64PDf",base64PDf);
        String currentDateTime = DateFormat.getDateTimeInstance().format(new Date());
        Calendar calendar=Calendar.getInstance();
      ;
        final File dwldsPath = new File(Environment.getExternalStoragePublicDirectory(
                Environment.DIRECTORY_DOWNLOADS) + "/Report" +   calendar.getTimeInMillis() + "_.xlsx");
        byte[] pdfAsBytes = Base64.decode(base64PDf.replaceFirst("data:application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;base64,", ""), 0);
            Log.e("bytearrya",""+pdfAsBytes);
        FileOutputStream os;
        os = new FileOutputStream(dwldsPath, false);
        os.write(pdfAsBytes);
        os.flush();
        os.close();

        if(dwldsPath.exists()) {
            sendNotification();


            File dir = new File(Environment.getExternalStoragePublicDirectory(
                    Environment.DIRECTORY_DOWNLOADS) + "/Report" +   
calendar.getTimeInMillis() + "_.xlsx");
            Intent sendIntent = new Intent(Intent.ACTION_VIEW);
         String path=   dir.getAbsolutePath();

            Uri uri;
            if (Build.VERSION.SDK_INT < 24) {
                uri = Uri.fromFile(dir);
            } else {
                File file = new File(path);
                uri = FileProvider.getUriForFile((MainActivity)this.context, 
this.context.getApplicationContext().getPackageName() + ".provider", file);
//                    uri = Uri.parse("file://" + dir); 
            }
            sendIntent.setDataAndType(uri, "application/vnd.ms-excel");
            sendIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            sendIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
            try{
                context.startActivity(sendIntent);

            }catch (Exception e){
                Toast.makeText(context, "Np app found to view file", Toast.LENGTH_SHORT).show();
            }

        }

    }
}
Himani Borse
  • 51
  • 1
  • 2
2

Android DownloadManager is designated for downloading remote files using HTTP / HTTPS protocols only. A blob is not a remote data, but something within your WebView. So the workaround is to convert the Blob into Base64 string and write it to a file.

Here is an another SO thread with decent example.

Manoj
  • 21,753
  • 3
  • 20
  • 41