起因
最近写了个简单项目,我直接用 Nuxt3 提供的 server 目录直接进行 API 开发,感觉比较方便。
写图片上传时却找不到方法,尝试许久后知道了如何解决,特此记录一下,方便以后用。
API
这里我用到了 formidable 这个包; 安装就不说了,简单说说如何配置。
首先做点简单的,配置一下 上传路径
以及 自动创建上传目录
,确保项目启动前路径存在
import fs from "fs";
// 上传路径
const uploadDir = "./public/img/uploads";
// 创建上传目录
fs.stat(uploadDir, (err, stats) => {
if (err) {
fs.mkdir(uploadDir, (err) => {
if (err) {
console.error("创建图片目录失败", err);
}
});
}
});
再来进行 formidable 配置,这里我配置了我目前要用的一些配置,例如:多文件、大小限制、扩展名保留、文件重命名、文件过滤
// 上传配置
const form = formidable({
uploadDir,
multiples: true, // 支持多文件
maxFileSize: 5 * 1024 * 1024, // 5MB 大小限制
keepExtensions: true, // 保留文件扩展名
// 文件名重命名
filename: (name: string, ext: string, part, form) => {
return `${name}-${new Date().getTime()}${ext}`;
},
// 文件过滤
filter: (part) => {
// 判断文件名是否为图片格式
if (part.originalFilename?.match(/\.(jpg|jpeg|png)$/i)) {
return true;
}
return false;
}
});
配置好之后,就可以使用 form
去调用 parse
方法进行文件保存
form.parse(event.node.req, (err, fields, files: any) => {
if (err) {
// error 处理
}
// 成功处理 files
});
直接放出整个 API 代码:
/*
* @Author: N0ts
* @Date: 2024-03-12 16:33:26
* @Description: 文件上传
* @FilePath: \bto\server\api\manage\file\index.post.ts
* @Mail:[email protected]
*/
import ResponseStatus from "@/server/type/ResponseStatus";
import formidable from "formidable";
import fs from "fs";
// 上传路径
const uploadDir = "./public/img/uploads";
// 创建上传目录
fs.stat(uploadDir, (err, stats) => {
if (err) {
fs.mkdir(uploadDir, (err) => {
if (err) {
console.error("创建图片目录失败", err);
}
});
}
});
export default defineEventHandler(async (event) => {
// 上传配置
const form = formidable({
uploadDir,
multiples: true, // 支持多文件
maxFileSize: 5 * 1024 * 1024, // 5MB 大小限制
keepExtensions: true, // 保留文件扩展名
// 文件名重命名
filename: (name: string, ext: string, part, form) => {
return `${name}-${new Date().getTime()}${ext}`;
},
// 文件过滤
filter: (part) => {
// 判断文件名是否为图片格式
if (part.originalFilename?.match(/\.(jpg|jpeg|png)$/i)) {
return true;
}
return false;
}
});
function upload() {
return new Promise((resolve, reject) => {
form.parse(event.node.req, (err, fields, files: any) => {
if (err) {
if (err.message.includes("options.maxTotalFileSize")) {
return reject("图片超出限制!最大限制 5MB");
}
return reject(err);
}
const result = [];
for (const key in files) {
result.push({
name: files[key][0].newFilename,
url: "/img/uploads/" + files[key][0].newFilename
});
}
resolve(result);
});
});
}
try {
const data = await upload();
return ResponseStatus.OK(data);
} catch (err: any) {
return ResponseStatus.ERROR(err);
}
});
这里我把上传操作写成了异步函数,方便在外面直接进行 return 结果。
成功后我将 files
的数据 push 到了数组,方便前端使用,也可根据自己业务处理数据。
调用测试:
文件超出大小限制:
完结撒花~
相关内容