美文网首页
Android—在WebView中下载Blob协议文件

Android—在WebView中下载Blob协议文件

作者: 东方未曦 | 来源:发表于2020-05-13 23:41 被阅读0次

    之前有个需求是要下载Blob协议的gif,让我苦恼了好久。平时下载http协议的文件时直接获取输入流即可,但是Java无法获得Blob协议的文件流,无法直接处理。不过JavaScript处理Blob协议非常方便,可以考虑通过前端将该文件转化为Base64的字符串。

    那么下载Blob协议文件时,可以先将链接传给前端,前端通过JS处理后得到Base64的文件流,再将文件流通过Android的JavaScript方法传给客户端。

    按这个逻辑,JS处理文件流这块需要前端开发,不过有意思的是,这部分功能我们可以直接在客户端写。如下方的getBase64StringFromBlobUrl()方法,将JS代码拼成String,调用WebView.loadUrl(...)加载这段JS代码即可,那么所有的流程都能在客户端实现。

    public 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);
        }
    
        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','image/gif');" +
                        "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');";
        }
    
        private void convertToGifAndProcess(String base64) {
            String currentDateTime = DateFormat.getDateTimeInstance().format(new Date());
            File gifFile = new File(Environment.getExternalStoragePublicDirectory(
                    Environment.DIRECTORY_DOWNLOADS) + "/Test_" + currentDateTime + "_.gif");
            saveGifToPath(base64, gifFile);
            Toast.makeText(mContext, R.string.save_image_success, Toast.LENGTH_SHORT).show();
            if (mDownloadGifSuccessListener != null) {
                mDownloadGifSuccessListener.downloadGifSuccess(gifFile.getAbsolutePath());
            }
        }
    
        private void saveGifToPath(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,并为WebView添加JavascriptInterface,最后通过loadUrl()方法执行JS代码即可。

    // 1. 新建WebView
    mWebView = new WebView(this);
    WebSettings webSettings = mWebView.getSettings();
    webSettings.setJavaScriptEnabled(true);
    webSettings.setAppCachePath(getApplicationContext().getCacheDir().getAbsolutePath());
    webSettings.setCacheMode(WebSettings.LOAD_DEFAULT);
    webSettings.setDatabaseEnabled(true);
    webSettings.setDomStorageEnabled(true);
    webSettings.setUseWideViewPort(true);
    webSettings.setLoadWithOverviewMode(true);
    webSettings.setPluginState(WebSettings.PluginState.ON);
    
    // 2. 添加JavascriptInterface
    mDownloadBlobFileJSInterface = new DownloadBlobFileJSInterface(this);
    mWebView.addJavascriptInterface(mDownloadBlobFileJSInterface, "Android");
    
    // 3. 执行JS代码
    mWebView.loadUrl(DownloadBlobFileJSInterface.getBase64StringFromBlobUrl(url));
    

    参考

    1. Download Blob file from Website inside Android WebViewClient

    相关文章

      网友评论

          本文标题:Android—在WebView中下载Blob协议文件

          本文链接:https://www.haomeiwen.com/subject/iqcywhtx.html