众所周知,uniapp的webview有特殊的安全策略,无法实现正常下载,下载会导致文件下载失败,那么该如何解决这个问题呢?官方提示可以将文件转blob、blob转base64进行下载,我研究了半天,发现这条路行不通,于是乎自己想出了另一方案。
背景说明:
APP为uniapp开发;
webview为泛微高代码平台开发的react的页面(这块经研究,应该啥语言开发的都可以,html、vue、react都行,无限制);
解决方案:
webview进行下载的时候,向uniapp发送消息,消息内容为文件的base64,让uniapp触发下载事件。
webview:
1、引入uniapp的webview.js文件
2、在页面中引用,调用流程需严格复制下面代码,不要进行编辑和修改
uni.webView.postMessage({
data: {
pdfFile: base64data
}
});
base64data需要自行将文件转成base64,这一步就省略了,如此webview就可以了。
app:
1、将base64转临时路径,方法如下
/**
* base64字符串转成文件
* @param {String} base64Str // 允许包含前缀
* @param {String} fileName // 文件名称:1663061363470.xlsx
* @param {Object} callback // 返回本地路径径URL,file:///xxx/doc/1663062980631.xlsx
*/
base64ToFile2(base64Str, fileName, callback) {
// 去除base64前缀
var index = base64Str.indexOf(',')
var base64Str = base64Str.slice(index + 1, base64Str.length)
plus.io.requestFileSystem(plus.io.PRIVATE_DOC, function(fs) {
fs.root.getFile(fileName, {
create: true
}, function(entry) {
// 获得本地路径URL,file:///xxx/doc/1663062980631.xlsx
var fullPath = entry.fullPath;
let platform = uni.getSystemInfoSync().platform
if (platform == 'android') {
var Base64 = plus.android.importClass("android.util.Base64");
var FileOutputStream = plus.android.importClass("java.io.FileOutputStream");
try {
var out = new FileOutputStream(fullPath);
// 此处Base64.decode有长度限制,如果不能满足需求,可以考虑换成官方原生插件市场的【Base64转文件】
var bytes = Base64.decode(base64Str, Base64.DEFAULT);
out.write(bytes);
out.close();
// 回调
callback && callback(entry.toLocalURL());
} catch (e) {
console.log(e.message);
}
} else if (platform == 'ios') {
var NSData = plus.ios.importClass('NSData');
var nsData = new NSData();
nsData = nsData.initWithBase64EncodedStringoptions(base64Str, 0);
if (nsData) {
nsData.plusCallMethod({
writeToFile: fullPath,
atomically: true
});
plus.ios.deleteObject(nsData);
}
// 回调
callback && callback(entry.toLocalURL());
}
})
})
}
方法就不解释了,复制进去即可。
2、webview编写@message事件:
<web-view @message="messageCallback" :src="url"> </web-view>
3、调用
/**
* 消息回调事件
* @param {Object} 回调参数
*/
messageCallback(data) {
uni.showLoading({
title:"文件下载中"
});
const urlPath = data.detail.data[0].pdfFile;
this.base64ToFile2(urlPath, new Date().getTime()+".pdf", function(path) {
uni.showToast({
icon:"none",
title:"文件保存成功,路径为:"+path,
duration:5000
})
plus.runtime.openFile(path); //用第三方程序打开文件
uni.hideLoading();
});
}
4、完美结束。