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

时间:2018-11-29 20:11:12

标签: javascript java android android-webview blob

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

Download Blob file from Website inside Android WebViewClient

但是,它对我不起作用。永远不会命中convertBase64StringToZipAndStoreIt中的断点。

更新:我发现我正在获取HTTP404。我尝试使用blobUrl和blobUrl.substring(5),结果两种方法都相同。不过,BLOB可以在Chrome中正常下载。

Webview设置:

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条件):

private boolean handleRequest(WebView view, String url) {
String filename;
if (!checkInternetConnection()) {
    ShowNetworkUnavailableDialog(false);
    return true;
}
else {
    if (url.contains("view/mys") || url.contains("view/myy") || url.contains("blob") || url.contains("view/mye")) {
        if (url.contains("view/mys")) {
            filename = getResources().getString(R.string.mys_file_name).concat(".pdf");
        } else if (url.contains("view/myy")) {
            filename = getResources().getString(R.string.form_file_name).concat(".pdf");
        } else if (url.contains("blob")) {
            filename = getResources().getString(R.string.mys_file_name).concat(".zip");
        } else {
            filename = getResources().getString(R.string.mye_file_name).concat(".pdf");
        }

        if (!url.contains("blob")) {
            String cookies = CookieManager.getInstance().getCookie(url);

            DownloadManager.Request downloadRequest = new DownloadManager.Request(Uri.parse(url));
            downloadRequest.addRequestHeader("cookie", cookies);
            downloadRequest.allowScanningByMediaScanner();
            downloadRequest.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
            downloadRequest.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, filename);
            DownloadManager dm = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);

            try {
                dm.enqueue(downloadRequest);
            } catch (SecurityException e) {
                Toast.makeText(getApplicationContext(), getResources().getString(R.string.connection_unavailable), Toast.LENGTH_LONG).show();
                return false;
            }
        } else {
            String blobURL = JavaScriptInterface.getBase64StringFromBlobUrl(url);
            mWebView.loadUrl(blobURL);
        }

        Toast.makeText(getApplicationContext(), getResources().getString(R.string.download_message), Toast.LENGTH_LONG).show();

        return true;
    } else if (!url.contains(getMetadata(getApplicationContext(), HOSTNAME))) {
        //Navigate to external site outside of webview e.g. Help site
        Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
        startActivity(intent);
        return true;
    } else if(url.contains(getResources().getString(R.string.about_url))) {
        mWebView.loadUrl(url);
        return false;
    } else {
        if (savedInstanceState == null) {
            mWebView.loadUrl(url);
        }
        return false;
    }
}

}

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获得相同的结果。

任何见识都将受到赞赏!

0 个答案:

没有答案