需求背景
公司所有的上传图片都很慢,原因是先把图片资源上传到公司服务器然后转存七牛云,公司服务器性能一般导致的。
h5页面要兼容微信客户端跟普通浏览器多图上传功能
解决方案
服务端提供七牛云上传token,前端直连七牛云省去了转存过程。
upload-token
七牛云直传文件
uniapp.uploadFile方法
实现
- 非微信客户端浏览器可直接调用uniapp中chooseImage方法
问题:浏览器中无法控制选择的数量,虽然选择后返回结果是指定数量,但是界面选择时可以任意选择
new Promise((resolve, reject) => {
uni.chooseImage({
count, //默认9
sizeType, //可以指定是原图还是压缩图,默认二者都有
sourceType, //从相册选择
success: function (res) {
// res.tempFilePaths[0]这个url就是uniapp.uploadFile方法中的filePath参数
// 示例:blob:http://192.168.1.121:5173/3662a774-8ee3-4be8-aa5e-9e3c18528e7d
resolve(res)
},
fail: (error) => {
reject(error)
}
});
})
- 微信客户端中,jssdk chooseImage 和 getLocalImgData
1. 先调chooseImage
2. 再把chooseImage返回的localIds使用getLocalImgData转成base64
3. 将base64文件转成二进制获取到blob对象,图片类型也可以拿到
4. 使用window.URL.createObjectURL(blob)方法转成url地址就可使用
uniapp.uploadFile方法中filePath上传了,当然也可以使用file对象(仅支持H5)
1. new Promise((resolve, reject) => {
wx.chooseImage({
count, // 默认9
sizeType, // 可以指定是原图还是压缩图,默认二者都有
sourceType, // 可以指定来源是相册还是相机,默认二者都有
success: function (res) {
resolve(res);
},
fail: (error) => {
reject(error)
}
})
})
2. new Promise((resolve, reject) => {
wx.getLocalImgData({
localId, // 微信相册选择图片的localID
success: function (res: any) {
const localData = res.localData;
let imageBase64 = '';
if (localData.indexOf('data:image') === 0) {
//苹果的直接赋值,默认生成'data:image/jpeg;base64,'的头部拼接
imageBase64 = localData;
} else {
//此处是安卓中的唯一得坑!在拼接前需要对localData进行换行符的全局替换
imageBase64 = 'data:image/jpeg;base64,' + localData.replace(/\n/g, '');
}
resolve(imageBase64);
},
fail: (error: any) => {
reject(error)
}
})
})
3. /**
* base64转为可post的二进制数据
*/
function dataURLtoBlob(dataurl) {
let arr = dataurl.split(',');
let mime = arr[0].match(/:(.*?);/)[1];
let bstr = atob(arr[1]);
let n = bstr.length;
let u8arr = new Uint8Array(n);
while (n--) {
u8arr[n] = bstr.charCodeAt(n);
}
return new Blob([u8arr], {
type: mime
});
}
4. const blob = dataURLtoBlob(localData); // localData是getLocalImgData方法返回的本地图片数据
const blobUrl = window.URL.createObjectURL(blob) || ''; // 转成bolb url地址
这个blobUrl就是uniapp.uploadFile中filePath参数url
// 示例:blob:http://192.168.1.121:5173/ae12feb2-965e-43dd-ab7f-d828a727ee73
直传七牛云 uniapp写法
const uploadTask = uni.uploadFile({
url: 'https://upload.qiniup.com/', // 七牛云上传存储区域我用的是华东-浙江 加速上传
filePath, // 图片本地地址url,blob:http://192.168.1.121:5173/ae12feb2-965e-43dd-ab7f-d828a727ee73
name: 'file',
formData, // {'token': '你的七牛云token', key: '设置图片名称key'}
success: (res) => {
try {
if (res.statusCode !== 200) return reject(res);
const dataString = res.data;
const dataObject = JSON.parse(dataString);
// 拼接fileURL 不管是qiniuShouldUseQiniuFileName true还是false 都需要拼接
dataObject.imageUrl = `${你的七牛云地址域名}/${dataObject.key}`;// key是上传到七牛云时传的图片key
// 生成图片示例{imageUrl: 'http://public.xxx.com/custcome/test/20230420165506_3528.jpg'}
resolve(dataObject);
} catch (e) {
reject(e);
}
},
fail: (error) => {
reject(error);
}
})
// 文件上传进度
uploadTask.onProgressUpdate((res) => {
progress && progress(res);
})
// 中断文件上传
cancelTask && cancelTask(() => {
uploadTask.abort();
})
})