最近在写项目时一直使用的是Elementui的Upload组件
照片墙的确很好用,不过会引发一些问题。
比如:
图片类型不对,fileList里是没有第二个文件的。但是照片墙已经显示了,我暂时将其视作bug吧。
解决办法:
upload有beforeUpload属性 可是该属性在我实验过后发现
只能适用于单个文件,多文件的照片墙可以正常拦截,不过
照片墙会出现显示BUG。并且为了节省OSS的开支,选择手动
上传。使用onchange的属性监控添加文件的type是否为图片
不是图片直接fileList.pop()移除,以免显示BUG。
代码:
<el-upload
action="/file/imgListUpload"
list-type="picture-card"
:limit="5"
ref="proof"
:before-upload="beforeUpload"
:auto-upload="false"
:on-change="changeFile"
:on-remove="handleRemove">
<i class="el-icon-plus" style="line-height:148px"></i>
</el-upload>
//手动上传的拦截 由于使用了手动上传 on-success不可用
changeFile(file, fileList){
const isJPG = file.raw.type === "image/jpeg" || "image/png" || "image/jpg"
const isLt2M = file.size / 1024 / 1024 < 5
//isJPG之所以不用!的方式是因为如果不符合上面的表达式会返回其他数据,!无法判断是否true
if (isJPG!=true) {
this.$message.error("上传图片只能是 JPG,JPEG,PNG 格式!")
fileList.pop();
}
if (!isLt2M) {
this.$message.error("上传图片大小不能超过 5MB!")
fileList.pop();
}
}
拦截类型不对的文件主要是upload的on-change的方法
监听每一次添加图片,这样如果添加了不对的图片直接将其从fileList里面清掉就不会出现显示BUG了
我这边是手动上传 所以使用了on-change
如果获取文件直接上传的话(auto-upload=true)就可以这样
//立即上传的拦截方案 根据上传成功以后返回的code 文件类型在后台判断
proofImgSuccess(res, file,fileList){
if(res.code === 200){
this.goodsErrorImgs.push(res.data);
}
else{
fileList.pop();
}
}
最后就是手动上传
upload的auto-upload关闭以后可以用
this.$refs.proof.submit()
进行手动上传。不过手动上传会加大方法的压力,如果使用OSS的并且在每次
上传后关闭连接的话建议synchronized锁住方法,以防线程
拿到连接以后被其他线程关闭,抛出500。
而且还有一个问题。如果要提交包括文件在内的其他表单内容的话,会拿不到返回的图片数据。例如response之类的。因为异步执行,执行submit以后会自动执行后面代码,假如打了console.log的话 console.log出来的有时候比submit还快…
而且console.log直接打印fileList的时候是会显示出response的属性,可是用Object.keys获取所有属性时却不存在response,很简单就是因为运行submit时console在submit没有执行完就执行了。说的有点多,也不知道解释清楚没。
我最终的选择是不用submit,拿到文件列表自己手动上传。submit不用,http-request覆盖也不用。就用this.$refs.proof.uploadFiles拿到待上传的文件。然后自己跑文件上传接口,用await修饰提交方法就可以让图片提交完毕以后再提交其他数据。
这是手动提交图片
async submitImgs(upLoadFiles){
var target = [];
for (var i=0; i<upLoadFiles.length;i++) {
let fileObj = upLoadFiles[i].raw;
let fd = new FormData();
fd.append("file",fileObj);
let config = {headers:{'Content-Type': 'multipart/form-data'}}
await axios.post("/file/imgListUpload",fd,config).then(res=>{
if(res.data.code == 200){
target.push(res.data.data);
}
})
}
target.forEach(item=>{
this.formLabelAlign.imgs = this.formLabelAlign.imgs+item+","
})
this.formLabelAlign.imgs = this.formLabelAlign.imgs.substring(0, this.formLabelAlign.imgs.lastIndexOf(','));
return true;
}
我后台存储的图片集URL由逗号分割,直接删除最后一个逗号以免切割出一个空值
文件上传要注意Content-type为multipart/form-data
upload的uploadFiles的raw就是一个文件
最后提交其他数据
async certification(formLabelAlign){
this.errorLoading = true;
await this.submitImgs(this.$refs.proof.uploadFiles)
this.$refs.formLabelAlign.validate((valid)=>{
if (valid) {
post("/goods/submitGoodsError",this.formLabelAlign).then(res=>{
//提交
})
}
else{
this.$message.error("请正确填写");
}
})
}
我这样写主要是节省OSS开支,用户点图片就上传了有时候会出现许多浪费的问题。
根据自己的业务需求来写其实才是最好的