直接上代码:
// app.js或者自己的路由文件
const fs = require("fs");
const path = require("path");
const koaBody = require("koa-body"); // npm i koa-body
const { format } = require("date-fns"); // npm i date-fns
// POST@/upload
router.post(
"/upload",
koaBody({
multipart: true, // 支持多文件上传
encoding: "gzip", // 编码格式
formidable: {
uploadDir: path.join(__dirname, "/public/upload/"), // 设置文件上传目录
keepExtensions: true, // 保持文件的后缀
maxFieldsSize: 10 * 1024 * 1024, // 文件上传大小限制
onFileBegin: (name, file) => {
// 无论是多文件还是单文件上传都会重复调用此函数
// 最终要保存到的文件夹目录
const dirName = format(new Date(), "yyyyMMddhhmmss");
const dir = path.join(__dirname, `public/upload/${dirName}`);
// 检查文件夹是否存在如果不存在则新建文件夹
if (!fs.existsSync(dir)) {
fs.mkdirSync(dir);
}
// 文件名称去掉特殊字符但保留原始文件名称
const fileName = file.name
.replaceAll(" ", "_")
.replace(/[`~!@#$%^&*()|\-=?;:'",<>\{\}\\\/]/gi, "_");
file.name = fileName;
// 覆盖文件存放的完整路径(保留原始名称)
file.path = `${dir}/${fileName}`;
},
onError: (error) => {
app.status = 400;
log4js.error(error);
// 这里可以定义自己的返回内容
app.body = { code: 400, msg: "上传失败", data: {} };
return;
},
},
}),
async (ctx) => {
try {
// 获取上传文件
const files = ctx.request.files;
// 正则 替换掉文件原始路径中不需要的部分
const reg = new RegExp(".*/upload/", "g");
for (const fileKey in files) {
ctx.uploadpaths = ctx.uploadpaths ? ctx.uploadpaths : [];
ctx.uploadpaths.push({
name: files[fileKey].name,
url: files[fileKey].path.replace(reg, ""),
});
}
ctx.body = { code: 200, msg: "", data:{ uploadpaths: ctx.uploadpaths }};
} catch (error) {
ctx.status = 400;
ctx.body = { code: 400, msg: "上传失败", data: {} };
}
}
);
主要是适配 Element Plus Upload 上传器组件
需要注意的是 这个组件的多文件上传其实是一个文件调用一次上传接口。
参考文章:
1、koa-body 文件上传自定义文件夹及文件名称
2、NodeJs koa2实现文件上传
参考的两篇文章有部分代码已不适用于最新情况,或者实现的业务逻辑与我自己的有冲突,所以我做了改动,不过仍然非常感谢两位作者的无私奉献。