项目中经常会用到文件上传的功能,为避免重复犯错,现将近阶段亲测过的方法,记录下
- 首先后端接口需求,需同时传文件
FormData
和其他所需参数,如下图所示:
- 前端简单的配置界面,如图所示,利
elementUI
组件el-upload
- 实现方法
关键点:
el-upload
的http-request
方法获取文件File
信息和FormData
方式传参
1.利用http-request
函数获取上传的文件File
信息
http-request
主要为覆盖默认的上传行为,可以自定义上传的实现,因需要实现手动上传,故应用到此方法
<template></template>
<template>
<el-upload
class="upload-demo"
ref="upload"
accept=".dat"
action=""
:http-request="httpRequest"
:auto-upload="false"
:file-list="fileList"
:on-change="handleFileChange"
>
<el-button slot="trigger" size="small" type="success">选取文件</el-button>
<div slot="tip" class="el-upload__tip" style="color: #ee4234">
{{ tips }}
</div>
</el-upload>
</template>
手动上传时,会触发
http-request
的回调函数httpRequest
httpRequest
方法
httpRequest(param) {
let fileObj = param.file; // 相当于input里取得的files
let fileName = fileObj.name;
let formData = new FormData(); // FormData 对象
formData.append("MultipartFile", fileObj); // 文件对象
formData.append("fileCreateName", fileName);//传递其他参数
this.$emit("upload", formData);
}
2.利用axio
的post
方法,实现与后端接口联调
关键点:设置
headers
为multipart/form-data
注意:uploadFile
方法为封装好的方法
//文件上传
export function uploadFile(formData) {
return request({
url: '/dataFileRecord/add',
method: 'post',
data: formData,
isFormData: true,
headers: {
'Content-Type': 'multipart/form-data'
}
})
}
3.完整代码,包括判断上传文件格式
和每次切换文件只显示最新选择的一个
自己封装的
Upload
组件
<template>
<el-upload
class="upload-demo"
ref="upload"
accept=".dat"
action=""
:http-request="httpRequest"
:auto-upload="false"
:file-list="fileList"
:on-change="handleFileChange"
>
<el-button slot="trigger" size="small" type="success">选取文件</el-button>
<div slot="tip" class="el-upload__tip" style="color: #ee4234">
{{ tips }}
</div>
</el-upload>
</template>
<script>
export default {
name: "upload",
data() {
return {
tips: "只能上传dat格式的文件",
fileList: [],
};
},
props: ["fileName"],
methods: {
init() {
this.fileList = [];
this.tips = "只能上传dat格式的文件";
},
httpRequest(param) {
let fileObj = param.file; // 相当于input里取得的files
let fileName = fileObj.name;
let formData = new FormData(); // FormData 对象
formData.append("MultipartFile", fileObj); // 文件对象
formData.append("fileCreateName", fileName);
this.$emit("upload", formData);
},
isFormatValid(type) {
let pStrDAt = /\.dat?$/i;
return pStrDAt.test(type);
},
handleFileChange(file, fileList) {
this.beforeUpload(file);
if (fileList.length > 0) {
this.fileList = [fileList[fileList.length - 1]]; // 这一步,是 展示最后一次选择的dat文件
}
},
beforeUpload(file) {
let fileName = file.name;
this.$emit("update:fileName", fileName);
let isDat = this.isFormatValid(fileName);
if (!isDat) {
this.tips = "当前选择的文件格式不正确,请重新选择!";
} else {
this.tips = "";
}
return isDat;
},
handleSubmit() {
if (!this.tips) {
this.$refs.upload.submit();
}
},
},
};
</script>
<style lang="scss" scoped>
.el-upload__tip {
color: #ee4234;
position: absolute;
top: 40px;
}
</style>
注意:点击确定按钮,调用组件
upload
的submit
方法,从而触发httpRequest
方法,实现手动上传
this.$refs.upload.submit();
主页面
<template>
<MainPanel
ref="panel"
:tableInfo="tableInfo"
:dialogInfo="dialogInfo"
@table-update="handlePageUpdate"
@table-edit="handleTableEdit"
@table-delete="handleTableDelete"
@btn-search="handleSearch"
@btn-add="handleAdd"
@btn-batch-delete="handleBatchDelete"
@dialog-confirm="handleDialogConfirm"
@dialog-cancel="handleDialogCancel"
>
<el-col :span="1" class="search-text">文件名称:</el-col>
<el-col :span="3">
<el-input
v-model="searchFileName"
placeholder="请输入文件名称"
style="width: 100%"
clearable
></el-input>
</el-col>
<template #dialog>
<el-col :span="6">
<Upload
v-if="!isEdit"
ref="upload"
:fileName.sync="fileName"
@upload="handleUpload"
></Upload>
</el-col>
</template>
</MainPanel>
</template>
<script>
import MainPanel from "@/components/MainPanel";
import { uploadFile, getFileList, updateFile, delFile } from "@/api/api.js";
import Upload from "@/components/Upload";
export default {
name: "fileManage",
data() {
var columns = [
{
label: "文件名称",
prop: "fileCreateName",
required: true,
},
{
label: "文件大小",
prop: "fileSize",
},
{
label: "文件类型",
prop: "fileType",
},
{
label: "创建时间",
prop: "createTime",
},
{
label: "更新时间",
prop: "updateTime",
},
];
var validateName = (rule, value, callback) => {
if (!this.dialogInfo.condition.fileCreateName) {
callback(new Error("文件名不能为空"));
} else {
callback();
}
};
return {
tableInfo: {
tableData: [],
columns: columns,
tableTotal: 0,
pageInfo: {},
},
dialogInfo: {
title: "文件上传",
columns: columns.filter((item) => item.required),
condition: {
fileCreateName: "",
},
dialogWidth: "50%",
rules: {
fileCreateName: [
{ required: true, validator: validateName, trigger: "blur" },
],
},
},
isEdit: false,
condition: {
pageNo: 1,
pageSize: 10,
},
currentId: "",
fileName: "",
searchFileName: "",
};
},
components: { MainPanel, Upload },
watch: {
fileName(val) {
this.dialogInfo.condition.fileCreateName = val;
},
},
mounted() {
//获取文件列表
this.getFileList();
},
methods: {
async getFileList() {
let pInfo = await getFileList(this.condition);
this.tableInfo.tableData = pInfo.data.data.content;
this.tableInfo.tableTotal = pInfo.data.data.totalElements;
},
handlePageUpdate(condition) {},
handleTableEdit(row) {
this.isEdit = true;
this.dialogInfo.title = "文件编辑";
this.currentId = row.id;
},
handleTableDelete(row) {
this.deleteFiles([row.id]);
},
handleBatchDelete(items) {
let idArray = items.map((item) => item.id);
this.deleteFiles(idArray);
},
handleAdd() {
this.isEdit = false;
this.dialogInfo.condition.fileCreateName = "";
if (this.$refs.upload) {
this.$refs.upload.init();
}
},
handleSearch() {
this.tableInfo.pageInfo = {
pageNo: 1,
pageSize: 10,
};
this.condition.pageNo = 1;
this.condition.pageSize = 10;
this.condition.param = JSON.stringify({
fileCreateName: this.searchFileName,
});
this.getFileList();
},
handleDialogConfirm() {
if (this.isEdit) {
this.updateFile();
} else {
if (this.$refs.upload) {
this.$refs.upload.handleSubmit();
}
}
},
handleDialogCancel() {
this.fileName = "";
},
addFile(formData) {
uploadFile(formData).then((res) => {
if (res.data.code === "0") {
this.handleSuccess("上传");
} else {
this.handleError("上传");
}
});
},
updateFile() {
updateFile({
fileCreateName: this.dialogInfo.condition.fileCreateName,
id: this.currentId,
}).then((res) => {
if (res.data.code === "0") {
this.handleSuccess("更新");
} else {
this.handleError("更新");
}
});
},
deleteFiles(idArray) {
delFile(idArray).then((res) => {
if (res.data.code === "0") {
this.handleSuccess("删除");
} else {
this.handleError("删除");
}
});
},
handleUpload(formData) {
this.addFile(formData);
},
handleSuccess(type) {
this.$message({
type: "success",
message: "文件" + type + "成功!",
});
if (this.$refs.panel) {
this.$refs.panel.init();
}
this.fileName = "";
this.getFileList();
},
handleError(type) {
this.$message({
type: "error",
message: "文件" + type + "失败,请检查服务连接!",
});
},
},
};
</script>
<style lang="scss" scoped>
</style>