Javascript 通过Android webview中的BLOB链接下载文件

Javascript 通过Android webview中的BLOB链接下载文件,javascript,java,android,android-webview,blob,Javascript,Java,Android,Android Webview,Blob,我有一个网站,是从一个网络视图导航。其中一个页面生成一个ZIP文件,该文件通过BLOB URL下载。我发现webview不支持这一点,因此我尝试实施此解决方案: 然而,这对我不起作用。convertBase64StringToZipAndStoreIt中的断点永远不会被命中 更新:我发现我得到了一个HTTP 404。我试过使用blobUrl和blobUrl.substring(5),结果都是一样的。不过,这些Blob在Chrome上下载得很好 网络视图设置: private void laun

我有一个网站,是从一个网络视图导航。其中一个页面生成一个ZIP文件,该文件通过BLOB URL下载。我发现webview不支持这一点,因此我尝试实施此解决方案:

然而,这对我不起作用。convertBase64StringToZipAndStoreIt中的断点永远不会被命中

更新:我发现我得到了一个HTTP 404。我试过使用blobUrl和blobUrl.substring(5),结果都是一样的。不过,这些Blob在Chrome上下载得很好

网络视图设置:

private void launchWV() {
    ActivityCompat.requestPermissions(this,
            new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
            1);
    setContentView(R.layout.activity_self_service_launcher);
    mWebView = (WebView) findViewById(R.id.activity_launcher_webview);

    WebSettings webSettings = mWebView.getSettings();

    webSettings.setBuiltInZoomControls(true);
    webSettings.setSupportZoom(true);
    webSettings.setJavaScriptEnabled(true);
    webSettings.setJavaScriptCanOpenWindowsAutomatically(true);
    webSettings.setSupportMultipleWindows(true);
    webSettings.setAllowContentAccess(true);
    webSettings.setAllowFileAccess(true);
    webSettings.setAllowFileAccessFromFileURLs(true);
    webSettings.setUserAgentString("Mozilla/5.0 (Android; X11; Linux x86_64) AppleWebKit/534.24 (KHTML, like Gecko) Chrome/11.0.696.34 Safari/534.24" + getClientVersionInfo());
    webSettings.setDomStorageEnabled(true);
    webSettings.setLoadWithOverviewMode(true);

    mWebView.setWebViewClient(new MyWebViewClient(this));
    mWebView.setWebChromeClient(new MyWebChromeClient(this));
    mWebView.addJavascriptInterface(new JavaScriptInterface(getApplicationContext()), "Android");
}
从shouldOverrideUrlLoading()调用的函数(只关注BLOB URL的else条件):

}

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 {
    convertBase64StringToZipAndStoreIt(base64Data);
}
public static String getBase64StringFromBlobUrl(String blobUrl){
    if(blobUrl.startsWith("blob")){
        return "javascript: var xhr = new XMLHttpRequest();" +
                "xhr.open('GET', '" + blobUrl.substring(5) + "', true);" +
                "xhr.setRequestHeader('Content-type','application/zip');" +
                "xhr.responseType = 'blob';" +
                "xhr.onload = function(e) {" +
                "    if (this.status == 200) {" +
                "        var blobZip = this.response;" +
                "        var reader = new FileReader();" +
                "        reader.readAsDataURL(blobZip);" +
                "        reader.onloadend = function() {" +
                "            base64data = reader.result;" +
                "            Android.getBase64FromBlobData(base64data);" +
                "        }" +
                "    }" +
                "};" +
                "xhr.send();";
    }
    return "javascript: console.log('It is not a Blob URL');";
}
private void convertBase64StringToZipAndStoreIt(String base64Zip) throws IOException {
    final int notificationId = 1;
    String currentDateTime = DateFormat.getDateTimeInstance().format(new Date());
    final File dwldsPath = new File(Environment.getExternalStoragePublicDirectory(
            Environment.DIRECTORY_DOWNLOADS) + "/YourFileName_" + currentDateTime + "_.zip");
    byte[] zipAsBytes = Base64.decode(base64Zip.replaceFirst("^data:application/zip;base64,", ""), 0);
    FileOutputStream os;
    os = new FileOutputStream(dwldsPath, false);
    os.write(zipAsBytes);
    os.flush();

    if(dwldsPath.exists()) {
        NotificationCompat.Builder b = new NotificationCompat.Builder(context, "MY_DL")
                .setDefaults(NotificationCompat.DEFAULT_ALL)
                .setWhen(System.currentTimeMillis())
                .setSmallIcon(R.drawable.ic_launcher_background)
                .setContentTitle("MY TITLE")
                .setContentText("MY TEXT CONTENT");
        nm = (NotificationManager) this.context.getSystemService(Context.NOTIFICATION_SERVICE);
        if(nm != null) {
            nm.notify(notificationId, b.build());
            Handler h = new Handler();
            long delayInMilliseconds = 5000;
            h.postDelayed(new Runnable() {
                public void run() {
                    nm.cancel(notificationId);
                }
            }, delayInMilliseconds);
        }
    }
}
}

我知道我不清楚的一件事是,在类中调用xhr.open时应该使用什么URL

我还尝试使用onDownloadStart,得到了相同的结果


非常感谢您的任何见解

嘿neal你找到解决办法了吗?
public class JavaScriptInterface {
private Context context;
private NotificationManager nm;
public JavaScriptInterface(Context context) {
    this.context = context;
}

@JavascriptInterface
public void getBase64FromBlobData(String base64Data) throws IOException {
    convertBase64StringToZipAndStoreIt(base64Data);
}
public static String getBase64StringFromBlobUrl(String blobUrl){
    if(blobUrl.startsWith("blob")){
        return "javascript: var xhr = new XMLHttpRequest();" +
                "xhr.open('GET', '" + blobUrl.substring(5) + "', true);" +
                "xhr.setRequestHeader('Content-type','application/zip');" +
                "xhr.responseType = 'blob';" +
                "xhr.onload = function(e) {" +
                "    if (this.status == 200) {" +
                "        var blobZip = this.response;" +
                "        var reader = new FileReader();" +
                "        reader.readAsDataURL(blobZip);" +
                "        reader.onloadend = function() {" +
                "            base64data = reader.result;" +
                "            Android.getBase64FromBlobData(base64data);" +
                "        }" +
                "    }" +
                "};" +
                "xhr.send();";
    }
    return "javascript: console.log('It is not a Blob URL');";
}
private void convertBase64StringToZipAndStoreIt(String base64Zip) throws IOException {
    final int notificationId = 1;
    String currentDateTime = DateFormat.getDateTimeInstance().format(new Date());
    final File dwldsPath = new File(Environment.getExternalStoragePublicDirectory(
            Environment.DIRECTORY_DOWNLOADS) + "/YourFileName_" + currentDateTime + "_.zip");
    byte[] zipAsBytes = Base64.decode(base64Zip.replaceFirst("^data:application/zip;base64,", ""), 0);
    FileOutputStream os;
    os = new FileOutputStream(dwldsPath, false);
    os.write(zipAsBytes);
    os.flush();

    if(dwldsPath.exists()) {
        NotificationCompat.Builder b = new NotificationCompat.Builder(context, "MY_DL")
                .setDefaults(NotificationCompat.DEFAULT_ALL)
                .setWhen(System.currentTimeMillis())
                .setSmallIcon(R.drawable.ic_launcher_background)
                .setContentTitle("MY TITLE")
                .setContentText("MY TEXT CONTENT");
        nm = (NotificationManager) this.context.getSystemService(Context.NOTIFICATION_SERVICE);
        if(nm != null) {
            nm.notify(notificationId, b.build());
            Handler h = new Handler();
            long delayInMilliseconds = 5000;
            h.postDelayed(new Runnable() {
                public void run() {
                    nm.cancel(notificationId);
                }
            }, delayInMilliseconds);
        }
    }
}