前言
昨天写了
JAVA整合阿里云OSS/VUE上传阿里云OSS
这篇文章,上传是没有问题了,但是在删除的时候有点问题,如果在只上传单张图片的场景下,el-upload是很方便搞定的,但是如果是多张图片,上传是没问题,但是如果上传后的图片要做删除操作还是有点恶心的,本文主要针对VUE端,废话先不多说,场景引入一下!
场景引入
代码如下
<template>
<div>
<el-upload
:limit="4"
accept=".png,.jpg"
list-type="picture-card"
:on-exceed="handleExceed"
:on-preview="handlePictureCardPreview"
:on-remove="handleRemove"
:http-request="fileUpload"
action="#"
multiple>
<i class="el-icon-plus"></i>
</el-upload>
</div>
</template>
<script>
export default {
name: "imgUpload",
data(){
return{
haveUploadImg:[],//成功上传OSS图片数据
dialogImageUrl: '',
dialogVisible: false,
}
},
methods:{
//OSS图片上传相关
//删除el-upload上显示图片
handleRemove (file, fileList) {
console.log(file, fileList);
},
//图片预览
handlePictureCardPreview (file) {
this.dialogImageUrl = file.url;
this.dialogVisible = true
},
//图片上传
fileUpload(param){
var _this=this;
this.$CommonUtil.fileUploadOss(param.file,500000,res=>{
_this.haveUploadImg.push(res);//将上传OSS的图片添加到haveUploadImg中
console.log("上传阿里云OSS后得到的访地址===>",res);
});
},
//超过图片上传限制
handleExceed (files, fileList) {
this.$message.warning(`当前限制选择 4 个文件,本次选择了 ${files.length} 个文件,共选择了 ${files.length + fileList.length} 个文件`)
},
}
}
</script>
OSS图片上传工具
let axios = require('axios')
import {getOssSignature} from "../server/common"
import {Notification} from "element-ui";
import SparkMD5 from "spark-md5";//MD5工具 npm install spark-md5 --save
const commonUtils={
/**
* 格式化文件大小
* @param size
* @returns {string}
*/
formFileSize(originalSize){
var size = "";
if( originalSize < 0.1 * 1024 ){ //如果小于0.1KB转化成B
size = originalSize.toFixed(2) + "B";
}else if(originalSize < 0.1 * 1024 * 1024 ){//如果小于0.1MB转化成KB
size = (originalSize / 1024).toFixed(2) + "KB";
}else if(originalSize < 0.1 * 1024 * 1024 * 1024){ //如果小于0.1GB转化成MB
size = (originalSize / (1024 * 1024)).toFixed(2) + "MB";
}else{ //其他转化成GB
size = (originalSize / (1024 * 1024 * 1024)).toFixed(2) + "GB";
}
var sizestr = size + "";
var len = sizestr.indexOf("\.");
var dec = sizestr.substr(len + 1, 2);
if(dec == "00"){//当小数点后为00时 去掉小数部分
return sizestr.substring(0,len) + sizestr.substr(len + 3,2);
}
return sizestr;
},
/**
* 文件MD5码
* @param file
* @param resFileMD5Name 返回方法(返回MD5文件名.xxx)
*/
fileMD5(file,resFileMD5Name){
let fileReader = new FileReader();
let spark = new SparkMD5.ArrayBuffer();
// 获取文件二进制数据
fileReader.readAsArrayBuffer(file);
fileReader.onload = function (e) {
spark.append(e.target.result);
resFileMD5Name(spark.end());
};
},
/**
* MD5.xxx
* @param file
* @param resFileMD5Name 返回方法(返回MD5文件名.xxx)
*/
fileMD5Suffix(file,resFileMD5Name){
let fileReader = new FileReader();
let spark = new SparkMD5.ArrayBuffer();
// 获取文件二进制数据
fileReader.readAsArrayBuffer(file);
fileReader.onload = function (e) {
let fileName=file.name.toString();
spark.append(e.target.result);
//console.log("fileName===>",fileName.substring(fileName.lastIndexOf(".")));
resFileMD5Name(spark.end()+fileName.substring(fileName.lastIndexOf(".")));
};
},
/**
* OSS上传工具
* @param file 文件
* @param maxSize 最大size
* @param resfun 回调方法(回调数据用的)
*/
fileUploadOss(file,maxSize,resfun){
let fileSize=file.size;//文件大小
let fileMD5Name;//MD5文件码
let fileName=file.name;//原始文件
//console.log("file===>",file);
//console.log("fileSize===>",fileSize);
//文件大小校验
if (fileSize>maxSize){
Notification({
title: '文件上传异常',
message: "超过最大上传大小",
type: 'info'
});
console.error("超过最大上传大小");
return;
}
//获取文件MD5码
this.fileMD5Suffix(file,resFileMD5Name=>{
//console.log("resFileMD5Name===>",resFileMD5Name);
fileMD5Name = resFileMD5Name;
});
//获取签名
getOssSignature().then(res =>{
//console.log("signature===>",res);
let sendData = new FormData();
sendData.append('OSSAccessKeyId', res.accessid);
sendData.append('policy', res.policy);
sendData.append('Signature', res.signature);
sendData.append('keys', res.dir);
sendData.append('key', res.dir + fileMD5Name);
sendData.append('success_action_status', 200); // 指定返回的状态码
sendData.append('file', file);
axios.post(res.host, sendData).then(res => {
//console.log("阿里云OSS上传成功===>",res);
//console.log("fileMD5Name===>",fileMD5Name);
//得到上传后完整访问路径
let fullImgUrl=Config.imgUrl + fileMD5Name;
//console.log('得到上传到阿里云的图片地址===>' + fullImgUrl)
//格式化文件size
let formFileSize = this.formFileSize(fileSize);
//返回上传数据对象
resfun({
url:fullImgUrl,//图片全路径
name:fileName,//原始文件名
imgDirUrl:res.dir + fileMD5Name,//加文件夹地址
size:formFileSize,//格式化后文件大小
});
})
}).catch(err =>{
console.error("获取阿里云签名失败")
});
}
}
export default commonUtils;
问题描述
我们如果在el-upload同时选中多张图片上传,那么就会调用多次fileUpload,这个没问题,fileUpload中OSS上传成功后我们将上传OSS的图片数据保存到haveUploadImg中,也就是这行代码
//图片上传
fileUpload(param){
console.log("param.file.uid===>",param.file.uid);
this.$CommonUtil.fileUploadOss(param.file,500000,res=>{
this.haveUploadImg.push(res);//将上传OSS的图片添加到haveUploadImg中
console.log("上传阿里云OSS后得到的访地址===>",res);
});
},
但是我们点击以上传图片上的删除按钮时
el-upload会调用handleRemove方法,那么这个在el-upload其实是已经将这张图片删除掉的,这里handleRemove方法其实是已经删除后的回调,那么我们这里虽然el-upload组件上显示的图片已经删除了,但是我们实际保存上传OSS图片的haveUploadImg中对应的图片还是没删除!
handleRemove方法
handleRemove方法有两个参数file和fileList,file代表的是当前删除的项,fileList代表的是删除后剩余的项,那么我们在这个方法中其实是无法通过file和fileList得到用户删除的到底是那张照片的,这里我刚开始想的是通过比对照片名称来删除,但是这个感觉不靠谱,虽然我们能在file得到文件名
解决
铺垫
查阅了一下资料后发现el-upload其实给每张上传的图片都会定一个uid,然后我们在handleRemove方法的file参数中也能拿到当前删除的图片的uid,那么我们改造下代码
代码改造
改造OSS上传工具代码,我们将每张上传OSS照片的uid也返回出去
//返回上传数据对象
resfun({
url:fullImgUrl,//图片全路径
name:fileName,//原始文件名
imgDirUrl:res.dir + fileMD5Name,//加文件夹地址
size:formFileSize,//格式化后文件大小
uid:file.uid//当前图片标识id el-upload提供
});
图片上传代码不变,那么此时我们res返回的数据中就多了图片的uid标识
//图片上传
fileUpload(param){
console.log("param.file.uid===>",param.file.uid);
this.$CommonUtil.fileUploadOss(param.file,500000,res=>{
this.haveUploadImg.push(res);//将上传OSS的图片添加到haveUploadImg中
console.log("上传阿里云OSS后得到的访地址===>",res);
});
},
改造handleRemove移除图片方法,也就是当我们点击el-upload上显示的图片的删除按钮时这里改造后代码就会通过当前删除图片的uid和haveUploadImg数组对象中的uid进行对比,然后得到下标,从而删除数据!
//移除图片 (移除el-upload上显示的图片+移除已上传的图片)
handleRemove (file) {//执行该方法时自动移除el-upload上显示的图片,所以方法体内只需要移除已上传的图片即可
console.log("el-upload上显示的图片移除的file.uid==>"+file.uid);
const index =this.haveUploadImg.findIndex(item => item.uid === file.uid)
this.haveUploadImg.splice(index, 1)//移除已上传的图片
},