公司H5项目文件上传用到了Vant Uploader文件上传组件,但是这个组件的坑属实是真的多,写这篇文章给大家分享一下,如果问题和我同样的话就不用纠结了,可以直接换组件了~~
问题1:我在谷歌浏览器的模拟器中测试可以,为什么在手机上却没有办法显示,如下图
这个问题总共是有2处坑
解决方案:
前端可以在图片上传前压缩图片,这类代码其他博客有很多,随便搜索下就有了,这里顺便也给大家贴出来,这里要注意,如果你使用过这个方法却失败了还是不行,有可能是因为你没有转换文件,与后端所需要的格式不一致,所以会导致失败
//这里是把上传的文件转换
dataURLtoFile(dataurl, filename) {
var arr = dataurl.split(","),
mime = arr[0].match(/:(.*?);/)[1],
bstr = atob(arr[1]),
n = bstr.length,
u8arr = new Uint8Array(n);
while (n--) {
u8arr[n] = bstr.charCodeAt(n);
}
return new File([u8arr], filename, {
type: mime });
}
然后就是压缩图片大小
if (/\/(?:jpeg|png)/i.test(event.file.type) && event.file.size > 500000) {
// 创建Canvas对象(画布)
let canvas = document.createElement("canvas");
// 获取对应的CanvasRenderingContext2D对象(画笔)
let context = canvas.getContext("2d");
// 创建新的图片对象
let img = new Image();
// 指定图片的DataURL(图片的base64编码数据)
img.src = event.content;
// 监听浏览器加载图片完成,然后进行进行绘制
img.onload = () => {
// 指定canvas画布大小,该大小为最后生成图片的大小
canvas.width = 400;
canvas.height = 300;
/* drawImage画布绘制的方法。(0,0)表示以Canvas画布左上角为起点,400,300是将图片按给定的像素进行缩小。
如果不指定缩小的像素图片将以图片原始大小进行绘制,图片像素如果大于画布将会从左上角开始按画布大小部分绘制图片,最后的图片就是张局部图。*/
context.drawImage(img, 0, 0, 400, 300);
// 将绘制完成的图片重新转化为base64编码,file.file.type为图片类型,0.92为默认压缩质量
event.content = canvas.toDataURL(event.file.type, 0.92);
let config = {
headers: {
//添加请求头
"Content-Type": "multipart/form-data"
}
};
let file = this.dataURLtoFile(event.content, "image");
// console.log(file)
let params = new FormData();
params.append("file", file);
let url = `这里写公司图片上传的接口`;
this.$http({
method: "POST",
url: process.env.MOBILE_ROOT + url,
data: params,
config
})
.then(res => {
if (res.code == 200) {
this.fileList.push({
url: res.result.url
});
// Indicator.close();
}
})
.catch(e => {
});
};
}
2.部分oppo,小米手机不支持这个组件,我自己实测了很多手机,例如苹果6,7,8,华为等等,在这些手机中oppo和小米部分型号手机是不支持Vant Uploader这个组件的,看到这里是不是欲哭无泪,辛辛苦苦大半天结果不兼容。。。
解决方案:
换另外的组件,比如说微信公用的api chooseImage(),这个方法是最合适,详细的使用方法可以去微信的开发文档里看,这里也把代码贴一下
//先判断下终端是什么
updateImg(style) {
this.style = style;
if (this.fromWhere == "wechat") {
//上传图片
this.chooseImage();
} else if (this.fromWhere == "ios") {
window.webkit.messageHandlers.uploadImage.postMessage({
body: [] });
} else if (this.fromWhere == "android") {
window.native.uploadImage();
}
},
//然后可以设置上传时最多上传几张,压缩图以及相片来源
chooseImage() {
this.$wx.chooseImage({
count: 1,
sizeType: ["compressed"], // 可以指定是原图还是压缩图,默认二者都有
sourceType: ["album", "camera"], // 可以指定来源是相册还是相机,默认二者都有
success: res => {
var localId = res.localIds[0]; // 返回选定照片的本地ID列表,localId可以作为img标签的src属性显示图片
this.uploadImg(localId);
}
});
},
//这里是获取图片上传后返回来的一个图片本地ID
uploadImg(localId) {
this.$wx.uploadImage({
localId: localId, // 需要上传的图片的本地ID,由chooseImage接口获得
isShowProgressTips: 1, // 默认为1,显示进度提示
success: res => {
let serverId = res.serverId;
this.setServer(serverId);
},
fail: function(error) {
Toast("上传错误,请稍候重试!");
}
});
}
//最后上传图片并回显
setServer(serverId) {
var url = "这里写公司图片上传的接口";
var formData = new FormData();
formData.append("mediaId", serverId);
this.$http({
method: "POST",
url: process.env.API_ROOT + url,
data: formData
})
.then(res => {
if (res.code == 200) {
if (this.style == 1) {
this.cardPositive = res.result;
this.passPort = res.result;
this.household = res.result;
} else {
this.cardBack = res.result;
}
}
})
.catch(e => {
});
},
总结:我太难了。。。(后续还有几个问题以后再写)