前言
在做萤石云视频时候,嵌入萤石云视频网站下载图片时,碰到了blob:链接开头的图片。在Pc web端下载是正常的,但是android web端却是不能下载。
百度了一下blob:
blob:https并不是一种协议,而是html5中blob对象在赋给video标签后生成的一串标记,blob对象对象包含的数据,浏览器内部会解析。
参考链接
- https://blog.csdn.net/wqq1027/article/details/102458681
- https://blog.csdn.net/xingyun89114/article/details/80699527
- https://blog.csdn.net/ListerCi/article/details/106109776
解决方案
1.设置webview,这是基础设置
WebSettings webSettings = webView.getSettings();
//基础设置
webSettings.setJavaScriptEnabled(true);
2.设置webview监听下载(因为是点击链接下载,所以不需要这一步的可以忽略)
//设置、下载监听
webView.setDownloadListener(new DownloadListener() {
@Override
public void onDownloadStart(String url, String userAgent, String contentDisposition, String mimetype, long contentLength) {
downBlobUrl(url);
}
});
3.使用js工具写好解析blob的代码(纯文本写也可,正确就行)
var request = new XMLHttpRequest();
request.open('GET', '" + url + "', true);
request.setRequestHeader('Content-type', 'text/plain');
request.responseType = 'blob';
request.onload = function (e) {
console.log('执行测试:' + this.status);
if (this.status === 200) {
var blobFile = this.response;
var reader = new FileReader();
reader.readAsDataURL(blobFile);
reader.onloadend = function () {
var base64data = reader.result;
window.java.down(base64data);
}
}
};
request.send();
4.设置webview 调试输出(查看webview输出信息,可忽略)
//加载、调试工具
webView.setWebChromeClient(new WebChromeClient() {
@Override
public boolean onConsoleMessage(ConsoleMessage consoleMessage) {
ZLog.e(TAG, consoleMessage.message());
return super.onConsoleMessage(consoleMessage);
}
});
5.注入java反射
webView.addJavascriptInterface(new Object() {
@JavascriptInterface
public void down(String base64) {
//这里收到下载解析的base64、做相关处理
Bitmap bitmap = Base64Util.base64ToPicture(base64);
Base64Util.savePictureToAlbum(getContext(), bitmap);
}
}, "java");
6.注入js(点击下载,java就会收到url,再将bloburl传给webview解析获取到base64文件)
/**
* 下载、Blob图片
*
* @param url
*/
private void downBlobUrl(String url) {
if (url.startsWith("blob")) {
String blob = " var request = new XMLHttpRequest();" +
" request.open('GET', '" + url + "', true);" +
" request.setRequestHeader('Content-type', 'text/plain');" +
" request.responseType = 'blob';" +
" request.onload = function (e) {" +
" console.log('执行测试:'+this.status);" +
" if (this.status === 200) {" +
" var blobFile = this.response;" +
" var reader = new FileReader();" +
" reader.readAsDataURL(blobFile);" +
" reader.onloadend = function() {" +
" var base64data = reader.result;" +
" window.java.down(base64data);" +
" }" +
" }" +
" };" +
" request.send();";
String js = "javascript:" + blob;
webView.loadUrl(js);
}
}
7.解析base64,将图片放到相册
/**
* 将图片base64数据转化为bitmap
*
* @param imgBase64
* @return
* @throws Exception
*/
public static Bitmap base64ToPicture(String imgBase64) throws Exception {
//处理头部
if (imgBase64.contains(",")) {
imgBase64 = imgBase64.split(",")[1];
}
//解码开始
byte[] decode = Base64.decode(imgBase64, Base64.DEFAULT);
Bitmap bitmap = BitmapFactory.decodeByteArray(decode, 0, decode.length);
return bitmap;
}
/**
* 将图片保存到相册并通知刷新
*
* @param mContext
* @param bitmap
* @throws Exception
*/
public static void savePictureToAlbum(Context mContext, Bitmap bitmap) throws Exception {
if (bitmap == null) {
return;
}
//把文件插入到系统图库
MediaStore.Images.Media.insertImage(mContext.getContentResolver(), bitmap, System.currentTimeMillis() + "", null);
//发送广播,通知图库更新
mContext.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.parse("file://" + "/sdcard/namecard/")));
}
PS
我这里的webview是加载了相关链接的,如果只需要处理下载blob文件直接loadUrl可能会出现跨域问题