ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

WebView下载适配blob协议

2026/9/25 17:54:25 拓冰建站 浏览量
WebView下载适配blob协议

Java无法获得Blob协议的文件流,无法直接处理。不过JavaScript处理Blob协议非常方便,可以考虑通过前端将该文件转化为Base64的字符串。

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


 1.新建DownloadBlobFileJSInterface

public class DownloadBlobFileJSInterface {private static String mimeType = "";private static String fileName = "";private Context mContext;private DownloadGifSuccessListener mDownloadGifSuccessListener;public DownloadBlobFileJSInterface(Context context) {this.mContext = context;}public void setDownloadGifSuccessListener(DownloadGifSuccessListener listener) {mDownloadGifSuccessListener = listener;}@JavascriptInterfacepublic void getBase64FromBlobData(String base64Data) {convertToGifAndProcess(base64Data);}public static String getBase64StringFromBlobUrl(String blobUrl, String fileMimeType, String urlFileName) {if (blobUrl.startsWith("blob")) {mimeType = fileMimeType;fileName = urlFileName;return "javascript: var xhr = new XMLHttpRequest();" + "xhr.open('GET', '" + blobUrl + "', true);" + "xhr.setRequestHeader('Content-type','" + fileMimeType + ";charset=UTF-8');" + "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) {File gifFile = new File(mContext.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS) + "/" + fileName);KLog.d("《《下载请求》》开始保存数据:\n" + base64 + "\n路径:" + gifFile.getPath().toString());saveGifToPath(base64, gifFile);Toast.makeText(mContext, "保存成功", Toast.LENGTH_SHORT).show();insertDownloadFileHistoryDb(fileName);if (mDownloadGifSuccessListener != null) {mDownloadGifSuccessListener.downloadGifSuccess(gifFile.getAbsolutePath());}}private void saveGifToPath(String base64, File gifFilePath) {try {byte[] fileBytes = Base64.decode(base64.replaceFirst("data:" + mimeType + ";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);}}

2.添加JavaScriptInterface

    binding.mWebview.addJavascriptInterface(new DownloadBlobFileJSInterface(this), "Android");

3.添加WebView下载拦截,并执行JS

 binding.mWebview.setDownloadListener(new DownloadListener() {/*** @param url  应该下载的内容的完整url* @param userAgent 用于下载的用户代理。* @param contentDisposition 内容处置http标头(如果存在)。* @param mimetype 服务器报告的内容的mimetype* @param contentLength  服务器报告的文件大小*/@Overridepublic void onDownloadStart(String url, String userAgent, String contentDisposition, String mimetype, long contentLength) {if (TextUtils.isEmpty(url)) {return;}if (url.startsWith("blob")) {String fileName = URLUtil.guessFileName(url, contentDisposition, mimetype);KLog.d("filename:" + fileName);// 3. 执行JS                
binding.mWebview.loadUrl(DownloadBlobFileJSInterface.getBase64StringFromBlobUrl(url, mimetype,fileName));return;}//TODO 其他协议下载方式  http https}});