安卓WebView中无法下载Blob文件类型

4

我想从Webview下载文件,但每次都出现错误(只能下载HTTP/HTTPS URI:blob:https://.)。

在我的代码中使用了以下内容:

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


你能尝试打印一下URL返回的内容吗?确保它没有任何额外的空格或不必要的字符。 - Manoj
这个错误是由于 Blob 类型导致的,它没有空格。 - user10522025
当错误与URL有关时,您是否可以至少分享一下您正在传递以进行下载的URL是什么。 - Manoj
我正在下载不同的文件。就像这样 ---> blob:https://xyz.../b53... 有一些限制,要在blob后面加上https。 - user10522025
2个回答

5
Blob URL 包含编码格式的 URL,因此您需要先将 URL 转换为 Base64 格式,然后将数据存储到文件中。为此,您需要使用 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();
            }

        }

    }
}

2

Android DownloadManager是专门用于使用HTTP/HTTPS协议下载远程文件的工具。Blob不是远程数据,而是在您的WebView中的内容。因此,解决方法是将Blob转换为Base64字符串并将其写入文件。

这里有另一个SO线程,其中包含不错的示例。


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