概要
文件上传这里用的是 element-Ui 的 el-upload 在文件上传前 前端读取文件内容 进行内容数据格式的校验 通过才可以进行上传 否则给出 异常提示
整体架构流程代码
<el-upload
:on-success="onSucess"
:on-error="uploadError"
:before-upload="beforeUpload"
:multiple="false"
class="upload-demo"
action="/api/ZTMM/ntmm-mmacct/upload"
:headers="headersParam"
:data="tbmmacct"
:show-file-list="false"
>
<el-tooltip
class="item"
effect="light"
content="请上传.xls格式文件"
placement="right"
>
<el-button size="small" v-if="uploadBtn"
><span style="color: #66b1ff">选取文件</span></el-button
>
</el-tooltip>
</el-upload>
beforeUpload(file) {
this.loading = true;
const isXLS = file.type === "application/vnd.ms-excel";
if (!isXLS) {
this.$message.error("上传文件只能是xls格式!");
this.loading = false;
return false;
}
// this.loading = true;
// 使用 FileReader 读取文件内容进行校验
const reader = new FileReader();
reader.onload = async (e) => {
const fileContent = e.target.result;
// 解析 Excel 文件内容
const workbook = XLSX.read(fileContent, { type: "array" });
const sheet = workbook.Sheets[workbook.SheetNames[0]]; // 获取第一个 sheet
const data = XLSX.utils.sheet_to_json(sheet); // 将 sheet 转为 JSON 数组
// 进行自定义的文件内容校验
if (await this.validateFileContent(data)) {
this.$message.success("文件内容校验通过");
this.loading = false;
this.uploadFile(file);
} else {
this.$message.error("文件为空或内容格式不符合要求, 请重新检查上传!");
this.loading = false;
return false; // 校验失败,阻止上传
}
};
// 读取文件内容
reader.readAsArrayBuffer(file);
// 返回 false,表示文件上传暂时被阻止,等待校验完成
return false;
},
uploadFile(file) {
// 手动触发上传,这里可以通过修改 `action` 或直接调用 `upload` 方法上传
const formData = new FormData();
formData.append("file", file);
// 进行自定义的上传请求
this.$axios
.post("/api/ZTMM/ntmm-mmacct/upload", formData, {
headers: {
"Content-Type": "multipart/form-data",
...this.headersParam, // 如果有额外的头部信息
},
params: this.tbmmacct, // 如果有额外的请求数据
})
.then((response) => {
this.$message.success("文件上传成功");
this.getFiles();
// 处理成功逻辑
})
.catch((error) => {
this.$message.error("文件上传失败");
// 处理错误逻辑
});
},
async validateFileContent(data) {
console.log(data, "daat");
if (data && data.length > 0) {
let newArr = data.slice(1);
// 转换数据格式
const transformedData = newArr.map((item) => ({
itemId: item["盘条到货记录导入模版"],
itemName: item["__EMPTY"],
arrivalQuantity: item["__EMPTY_1"],
expectedArrivalTime: item["__EMPTY_2"],
creUser: item["__EMPTY_3"],
creTime: item["__EMPTY_4"],
}));
return this.validateData(transformedData);
}
return false; // 如果文件没有符合的内容,返回 false
},
validateData(data) {
if (data.length === 0) {
return false;
}
for (const item of data) {
// 校验 itemId
if (
typeof item.itemId !== "string" ||
item.itemId.length < 1 ||
item.itemId.length > 14 ||
item.itemId === null ||
item.itemId === undefined
) {
return false;
}
// 校验 itemName
if (
typeof item.itemName !== "string" ||
item.itemName.length < 1 ||
item.itemName.length > 10 ||
item.itemName === null ||
item.itemName === undefined
) {
return false;
}
// 校验 arrivalQuantity
const arrivalQuantity = parseInt(item.arrivalQuantity, 10);
if (
isNaN(arrivalQuantity) ||
arrivalQuantity < 1 ||
item.arrivalQuantity.length < 1 ||
item.arrivalQuantity.length > 2 ||
item.arrivalQuantity === null ||
item.arrivalQuantity === undefined
) {
return false;
}
// 校验 expectedArrivalTime
const expectedArrivalTime = new Date(item.expectedArrivalTime);
if (
isNaN(expectedArrivalTime.getTime()) ||
item.expectedArrivalTime === null ||
item.expectedArrivalTime === undefined
) {
return false;
}
// // 校验 creUser
// if (typeof item.creUser !== "string" || item.creUser.length < 1 || item.creUser === null || item.creUser === undefined) {
// return false;
// }
// // 校验 creTime
// if (typeof item.creTime !== "string" || item.creTime.length < 1 || item.creTime === null || item.creTime === undefined) {
// return false;
// }
}
return true; // 所有校验通过
},
技术细节
主要是在 beforeUpload 属性方法里实现 文件的校验与抓取,
// 使用 FileReader 读取文件内容进行校验
const reader = new FileReader();
reader.onload = async (e) => {
const fileContent = e.target.result;
// 解析 Excel 文件内容
const workbook = XLSX.read(fileContent, { type: "array" });
const sheet = workbook.Sheets[workbook.SheetNames[0]]; // 获取第一个 sheet
const data = XLSX.utils.sheet_to_json(sheet); // 将 sheet 转为 JSON 数组
// 进行自定义的文件内容校验
if (await this.validateFileContent(data)) {
this.$message.success("文件内容校验通过");
this.loading = false;
this.uploadFile(file);
} else {
this.$message.error("文件为空或内容格式不符合要求, 请重新检查上传!");
this.loading = false;
return false; // 校验失败,阻止上传
}
};
// 读取文件内容
reader.readAsArrayBuffer(file);
// 返回 false,表示文件上传暂时被阻止,等待校验完成
return false;
校验成功后需要手动去 抛送一下 uploadFile 以上代码有展示。
小结
组件结构
-
<el-upload>
组件::on-success
和:on-error
用于处理上传成功和失败的回调。:before-upload
是一个钩子函数,在文件上传之前进行校验。:multiple
设置为false
,表示只允许上传一个文件。action
指定文件上传的接口地址。:headers
和:data
用于传递额外的请求头和数据。:show-file-list
设置为false
,表示不显示文件列表。
-
<el-tooltip>
和<el-button>
:- 提供用户界面,提示用户上传
.xls
格式的文件。
- 提供用户界面,提示用户上传
方法解析
-
beforeUpload(file)
:- 在文件上传之前被调用。
- 检查文件类型是否为
.xls
,如果不是,则显示错误信息并停止上传。 - 使用
FileReader
读取文件内容,并在读取完成后解析 Excel 文件。 - 调用
validateFileContent(data)
方法对文件内容进行校验,如果通过,则调用uploadFile(file)
方法进行上传。
-
uploadFile(file)
:- 创建一个
FormData
对象,将文件添加到其中。 - 使用 Axios 发送 POST 请求上传文件,并处理成功和失败的回调。
- 创建一个
-
validateFileContent(data)
:- 对解析后的 Excel 数据进行校验。
- 将数据转换为特定格式,并调用
validateData(transformedData)
方法进行详细校验。
-
validateData(data)
:- 对每一项数据进行校验,包括
itemId
、itemName
、arrivalQuantity
和expectedArrivalTime
。 - 检查数据的类型、长度和有效性,确保符合要求。
- 对每一项数据进行校验,包括
总结
代码实现了一个完整的文件上传功能,包含了文件类型检查、内容校验和上传请求。通过这些方法,确保用户上传的文件符合预期的格式和内容要求,从而提高了数据的准确性和可靠性。