使用el-upload组件,支持批量上传和图片压缩。
前端需要引入 image-conversion
multiple设置为true,允许批量上传
auto-upload设置为false,关闭自动上传
在on-change的时候校验文件名和文件大小
增加一个上传到服务器的按钮
<template>
<div class="">
<el-upload ref="pictureUpload"
:multiple="true"
:action="uploadFileUrl"
list-type="picture-card"
:disabled="check"
:on-change="handleOnChange"
:before-upload="beforUpload"
:on-success="handleUploadSuccess"
:auto-upload="false"
:file-list="showFile">
<i slot="default"
class="el-icon-plus"></i>
<div slot="file"
slot-scope="{file}">
<img class="el-upload-list__item-thumbnail"
:src="file.url"
alt="">
<span class="el-upload-list__item-actions">
<span class="el-upload-list__item-preview"
:disabled="true"
@click="handlePictureCardPreview(file)">
<i class="el-icon-zoom-in"></i>
</span>
<span v-if="!check"
class="el-upload-list__item-delete"
@click="handleRemoveThis(file)">
<i class="el-icon-delete"></i>
</span>
</span>
</div>
</el-upload>
<el-button style="margin-left: 10px;"
size="small"
v-if="!check"
type="success"
@click="submitUpload">图片提交到服务器</el-button>
<el-dialog :visible.sync="dialogVisible"
title="预览"
width="800"
append-to-body>
<img :src="dialogImageUrl"
style="display: block; max-width: 100%; margin: 0 auto;">
</el-dialog>
</div>
</template>
<script>
import { getToken } from "@/utils/auth";
import * as imageConversion from 'image-conversion';
import { delImg } from "@/api/system/vote"
export default {
name: 'jImageUpload',
props: ['imageUrl', 'check'],
data () {
return {
AllLoading: [],
oldImg: null,
dialogImageUrl: '',
checkUpload: false,
fileList: [],
returnFileList: [],
showFile: [],
urlStr: [],
editFile: [],
dialogVisible: false,
uploadFileUrl: process.env.VUE_APP_BASE_API + "/sys/minio/upload", // 上传的图片服务器地址
headers: {
Authorization: "Bearer " + getToken(),
},
};
},
mounted () { // 在mounted时候赋值,子组件只更新一次,后面重新选择后展示此组件的数据,不再更新
this.oldImg = this.imageUrl
this.stringToImage(this.oldImg)
},
watch: {
imageUrl: function (val) {
// // console.log('val')
// // console.log(val)
this.oldImg = val
this.stringToImage(this.oldImg)
}
},
created () {
},
methods: {
stringToImage (imageString) {
this.showFile = []
this.editFile = []
if (imageString != null && imageString != '' && imageString != undefined) {
this.urlStr = imageString.split(",");
this.urlStr.forEach(item => {
let obj = new Object();
let obj1 = new Object();
obj1.url = item;
if (item.indexOf("http") < 0) {
item = process.env.VUE_APP_BASE_MINIO_API + item;
}
obj.url = item;
this.showFile.push(obj);
this.editFile.push(obj1);
});
}
},
arryToString (arry) {
var imgString = ""
if (arry.length > 0) {
for (var i = 0; i < arry.length; i++) {
if (i < arry.length - 1) {
imgString += arry[i].url + ",";
} else {
imgString += arry[i].url
}
}
}
return imgString
},
// 点击查看图片
handlePictureCardPreview (file) {
this.dialogImageUrl = file.url;
this.dialogVisible = true;
},
handleOnChange (file, fileList) {
if (file.name.indexOf(',') !== -1) {
this.msgError("上传的文件名称中不允许出现英文逗号!");
this.handleRemoveThis(file)
return false
} else {
const isLt2M = file.size / 1024 / 1024 < 1;
if (!isLt2M) {
console.log(file)
// return new Promise((resolve) => {
// 压缩到600KB,这里的600就是要压缩的大小,可自定义
imageConversion.compressAccurately(file.raw, 600).then(res => {
file.raw = new window.File([res], file.name, { type: file.type })
file.size = file.raw.size
this.fileList.push(file)
});
// })
} else {
this.fileList.push(file)
}
}
},
// 文件上传
submitUpload () {
// 全屏禁用开启
this.AllLoading = this.$loading({
lock: true,
text: '图片上传中...',
spinner: 'el-icon-loading',
background: 'rgba(0, 0, 0, 0.7)'
})
let fileList = []
let { uploadFiles, action, data } = this.$refs.pictureUpload
// console.log(uploadFiles)
// uploadFiles.forEach(file => {
// imageConversion.compressAccurately(file.raw, 600).then(res => {
// file.raw = new window.File([res], file.name, { type: file.type })
// file.size = file.raw.size
// });
// })
// console.log(uploadFiles)
this.uploadFiles({
uploadFiles,
data,
action,
success: (response) => {
var res = JSON.parse(response)
// this.$refs.uploadFile.clearFiles();
// console.log(res)
this.msgSuccess("图片上传成功!")
this.AllLoading.close()
res.data.fileName.forEach(item => {
let obj = new Object();
let obj1 = new Object();
obj.url = process.env.VUE_APP_BASE_MINIO_API + item;
obj1.url = item;
this.editFile.push(obj1)
this.showFile.push(obj)
var imgString = this.arryToString(this.editFile)
this.$emit('returnUrl', imgString)
})
},
error: (error) => {
this.msgError("图片上传失败!")
this.AllLoading.close()
console.log('图片上传失败!', error)
}
})
},
/**
* 自定义上传文件
* @param fileList 文件列表
* @param data 上传时附带的额外参数
* @param url 上传的URL地址
* @param success 成功回调
* @param error 失败回调
*/
uploadFiles ({ uploadFiles, headers, data, action, success, error }) {
let form = new FormData()
// 文件对象
uploadFiles.map(file => form.append("filedatas", file.raw))
// 附件参数
for (let key in data) {
form.append(key, data[key])
}
let xhr = new XMLHttpRequest()
// 异步请求
xhr.open("post", action, true)
// 设置请求头
xhr.setRequestHeader("Authorization", getToken());
xhr.onreadystatechange = function () {
if (xhr.readyState == 4) {
if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304) {
success && success(xhr.responseText)
} else {
error && error(xhr.status)
}
}
}
xhr.send(form)
},
// 移除图片
handleRemoveThis (file) {
// console.log(file)
// 在控件中移除图片
this.$refs.pictureUpload.handleRemove(file)
// 获取图片在数组中的位置
var number = this.showFile.indexOf(file)
// 获取返回的文件url中此文件的url
var file = process.env.VUE_APP_BASE_MINIO_API + this.editFile[number].url.toString()
var fileItemList = file.split('/')
// 执行文件删除
delImg(fileItemList[4]).then(response => {
// // console.log(response)
})
this.editFile.splice(number, 1)
this.showFile.splice(number, 1)
var imgString = this.arryToString(this.editFile)
this.$emit('returnUrl', imgString)
},
// 上传前
beforUpload (file) {
console.log("上传之前")
console.log(file)
if (file.name.indexOf(',') !== -1) {
this.msgError("上传的文件名称中不允许出现英文逗号!");
return false
} else {
// this.checkUpload = true
this.fileList.push(file)
const isLt2M = file.size / 1024 / 1024 < 1;
if (!isLt2M) {
return new Promise((resolve) => {
// 压缩到100KB,这里的100就是要压缩的大小,可自定义
imageConversion.compressAccurately(file.raw, 600).then(res => {
resolve(res);
});
})
}
}
},
// 上传成功
handleUploadSuccess (res, file, fileList) {
// this.checkUpload = false
// console.log("上传成功")
// console.log(res)
// console.log(fileList)
console.log(this.$refs.pictureUpload.uploadFiles)
this.$message.success("上传成功");
// fileList.forEach(item => {
// let obj = new Object();
// let obj1 = new Object();
// if (item.response !== undefined) {
// obj.url = process.env.VUE_APP_BASE_MINIO_API + item.response.fileName;
// obj1.url = item.response.fileName;
// this.editFile.push(obj1)
// this.showFile.push(obj)
// var imgString = this.arryToString(this.editFile)
// this.$emit('returnUrl', imgString)
// }
// })
let obj = new Object();
let obj1 = new Object();
obj.url = process.env.VUE_APP_BASE_MINIO_API + res.fileName;
obj1.url = res.fileName;
this.editFile.push(obj1)
this.showFile.push(obj)
var imgString = this.arryToString(this.editFile)
this.$emit('returnUrl', imgString)
},
handleUploadError () {
this.$message({
type: "error",
message: "上传失败",
});
this.loading.close();
},
},
};
</script>
<style scoped lang="scss">
.image {
position: relative;
.mask {
opacity: 0;
position: absolute;
top: 0;
width: 100%;
background-color: rgba(0, 0, 0, 0.5);
transition: all 0.3s;
}
&:hover .mask {
opacity: 1;
}
}
</style>