最近做了一个后台系统,里面有好多复杂的功能。其中就有上传的功能点,上传的时候,我们要校验上传的文件格式,限制上传的数量,自定义上传接口,可以拖拽上传,可以进行删除、预览,删除之后再次上传的时候会重现计算(这个时候要清除前一次上传的缓存列表)等等,于是就把这块好好总结一下,后面再用到就直接搬就行了。
<el-table-column
prop="dataUpload"
label="资料上传"
width="440"
>
<template #default="{ row }">
<el-upload
class="upload-demo"
drag
action="#"
multiple
:disabled="isEdittable != 'true'"
:show-file-list="false"
:http-request="
(file) => uploadfile(file, row)
"
:before-upload="
(file) => beforeUpload(file, row)
"
:limit="
row.docType == 'other' ? 999 : 1
"
:on-exceed="exceedFile"
:ref="
(el) =>
setRefs(
el,
row.id
)
"
>
<el-icon class="el-icon--upload"
><upload-filled
/></el-icon>
<div
class="el-upload__text"
>
拖拽图片到此处,或
<em>点此处选择文件</em>
</div>
</el-upload>
</template>
</el-table-column>
<script setup>
// 获取当前上传文件的html元素
const setRefs = (el, id) => {
if (el) {
if (!itemRefs.value.some((item) => item.id == id)) {
itemRefs.value.push({
id: id,
el,
});
}
}
};
//上传文件前校验文件类型
const beforeUpload = (file, row) => {
// 做上传前的一些校验操作
};
// 超出限制文件数量的钩子函数
const exceedFile = () => {
message.warning("只能上传一个文件");
};
// 上传文件处理函数
const uploadfile = async (file, row) => {
if (file.file.size == 0) {
return message.warning("文件内容为空,无法上传");
}
form.set("file", file.file);
form.set("type", row.type);
form.set("id", row.id);
form.set("docType", row.docType);
const loading = loading.service({
fullscreen: true,
background: "rgba(0,0,0,0.7)",
text: "文件上传中",
});
try {
const res = await API.upload(form);
if (res.data.code === "000000") {
row.files.push({
name: res.data.name,
id: res.data.id,
nailid: res.data.nailid,
nailid: res.data.nailid,
});
loading.close();
message.success("文件上传成功");
} else {
message.error(res.data.message);
}
} catch (error) {
loading.close();
message.error("文件上传失败请重试");
} finally {
loading.close();
if (itemRefs.value.length > 0) {
itemRefs.value.forEach((item) => {
if (item.id == row.recordItemId) {
item.el.clearFiles();
}
});
}
}
};
</script>
首先我用的ui组件是elementPlus,所以标签名是el-upload;
如果要实现拖拽功能,需要给el-upload标签加上drag属性;
如果要实现上传时多选文件的功能,需要给el-upload标签加上multiple属性;
如果要实现是否可以上传,需要给el-upload标签加上disabled属性;
如果要实现自定义上传操作(自己写函数,并定义上传接口),需要给el-upload标签加上http-request属性,并赋予它对应的方法;
如果要实现上传前做校验,需要给el-upload标签加上before-upload属性,并赋予它对应的方法;
如果要实现上传时限制上传的文件数量,需要给el-upload标签加上limit属性;
如果要实现上传时超出限制上传的文件数量时,,需要给el-upload标签加上on-exceed属性,加上对应的钩子函数即可;
如果要获取上传文件的这个html元素,需要加上ref这个属性,但是因为上传文件el-upload这个元素是相当于v-for这样生成的,所以会获取到许多el-upload元素,这个时候需要有唯一的id和对应的el-upload元素来一一对应,所以会有一个id来对应;
对于下载,后端返回的都是一个文件流,所以要对文件流做处理;
// 处理下载文件的方法
function downLoadXls(res) {
const fileNames = res.headers["content-disposition"];
if (fileNames) {
//解码
const fileName = decodeURIComponent(fileNames.match(/=(.*)$/)[1]);
// 处理返回的文件流
const content = res.data;
const blob = new Blob([content], {
type: "application/octet-stream; charset=utf-8",
});
if ("download" in document.createElement("a")) {
//非IE下载
const a = document.createElement("a"); //创建一个a标签
a.download = fileName; //指定文件名称
a.style.display = "none"; //页面隐藏
a.href = URL.createObjectURL(blob); // href用于下载地址
document.body.appendChild(a); //插到页面上
a.click(); //通过点击触发
URL.revokeObjectURL(a.href); //释放URL 对象
document.body.removeChild(a); //删掉a标签
} else {
//IE10 + 下载
navigator.msSaveBlob(blob, fileName);
}
}
}