Android WebView支持下载blob协议文件

2,321 阅读1分钟

此方法只适合下载图片等比较小的文件,文件过大会导致内存溢出崩溃

android 原生是不支持blob协议的,但是前端支持,可以让前端把文件转换为base64格式的文件传递给我们,当然我们自己也可以实现,实现代码如下:

public static class DownloadBlobFileJSInterface {

        private Context mContext;
        private DownloadGifSuccessListener mDownloadGifSuccessListener;

        public DownloadBlobFileJSInterface(Context context) {
            this.mContext = context;
        }

        public void setDownloadGifSuccessListener(DownloadGifSuccessListener listener) {
            mDownloadGifSuccessListener = listener;
        }

        @JavascriptInterface
        public void getBase64FromBlobData(String base64Data) {
            convertToGifAndProcess(base64Data);
        }

        /**
         * 插入js代码,转换成base64
         * @param blobUrl 获取到的url
         * @return
         */
        public static String getBase64StringFromBlobUrl(String blobUrl) {
            if (blobUrl.startsWith("blob")) {
                return "javascript: var xhr = new XMLHttpRequest();" +
                        "xhr.open('GET', '" + blobUrl + "', true);" +
                        "xhr.responseType = 'blob';" +
                        "xhr.onload = function(e) {" +
                        "    if (this.status == 200) {" +
                        "        var blobFile = this.response;" +
                        "        var reader = new FileReader();" +
                        "        reader.readAsDataURL(blobFile);" +
                        "        reader.onloadend = function() {" +
                        "            base64data = reader.result;" +
                        "            Android.getBase64FromBlobData(base64data);" +
                        "        }" +
                        "    }" +
                        "};" +
                        "xhr.send();";
            }
            return "javascript: console.log('It is not a Blob URL');";
        }

        /**
         * 转换成file
         * @param base64
         */
        private void convertToGifAndProcess(String base64) {
            File gifFile = new File(Environment.getExternalStoragePublicDirectory(
                    Environment.DIRECTORY_DOWNLOADS) + "/" + fileName);
            saveFileToPath(base64, gifFile);
            if (mDownloadGifSuccessListener != null) {
                mDownloadGifSuccessListener.downloadGifSuccess(gifFile.getAbsolutePath());
            }
        }
        /**
         * 保存文件
         * @param base64
         * @param gifFilePath
         */
        private void saveFileToPath(String base64, File gifFilePath) {
            try {
                byte[] fileBytes = Base64.decode(base64.replaceFirst(
                        "data:image/gif;base64,", ""), 0);
                FileOutputStream os = new FileOutputStream(gifFilePath, false);
                os.write(fileBytes);
                os.flush();
                os.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        public interface DownloadGifSuccessListener {
            void downloadGifSuccess(String absolutePath);
        }
    }

webview配置

mWebSettings.setJavaScriptEnabled(true);

mWebSettings.setJavaScriptCanOpenWindowsAutomatically(true); 

mDownloadBlobFileJSInterface = new DownloadBlobFileJSInterface(this);

webView.addJavascriptInterface(mDownloadBlobFileJSInterface, "Android");

mDownloadBlobFileJSInterface.setDownloadGifSuccessListener(absolutePath -> Toast.makeText(MainActivity.this,"下载成功,在Download目录下",Toast.LENGTH_SHORT).show());

webView.setDownloadListener((url, userAgent, contentDisposition, mimeType, contentLength) -> {
            webView.loadUrl(DownloadBlobFileJSInterface.getBase64StringFromBlobUrl(url));
        });
      

下载的文件名及格式需要自己判断,目前这个方法只能下载还不能判断格式及文件名