web-01-api/src/common/middlewares/upload.middleware.ts

64 lines
1.9 KiB
TypeScript
Raw Normal View History

2026-06-22 10:26:29 +08:00
import {
Injectable,
NestMiddleware,
BadRequestException,
} from '@nestjs/common';
import { Request, Response, NextFunction } from 'express';
import multer, { Multer } from 'multer';
import path from 'path';
import fs from 'fs';
const ALLOWED_MIME = ['image/jpeg', 'image/png', 'image/webp'];
const MAX_SIZE = 2 * 1024 * 1024; // 2M
/**
*
* file
*/
@Injectable()
export class UploadMiddleware implements NestMiddleware {
private readonly upload: Multer;
constructor() {
const root = process.env.UPLOAD_ROOT ?? './uploads';
this.upload = multer({
storage: multer.diskStorage({
destination: (_req, _file, cb) => {
const date = new Date();
const dir = path.join(
process.cwd(),
root.replace(/^\.\/?/, ''),
`${date.getFullYear()}/${String(date.getMonth() + 1).padStart(2, '0')}`,
);
fs.mkdirSync(dir, { recursive: true });
cb(null, dir);
},
filename: (_req, file, cb) => {
const ext = path.extname(file.originalname).toLowerCase();
const name = `${Date.now()}_${Math.random().toString(36).slice(2, 8)}${ext}`;
cb(null, name);
},
}),
fileFilter: (_req, file, cb) => {
if (ALLOWED_MIME.includes(file.mimetype)) {
cb(null, true);
} else {
// FileFilterCallback 重载:错误时只传 Error不传 acceptFile
cb(new Error('仅支持 jpg/png/jpeg/webp 格式图片'));
}
},
limits: { fileSize: MAX_SIZE },
});
}
use(req: Request, _res: Response, next: NextFunction): void {
this.upload.single('file')(req, _res, (err) => {
if (err) {
next(new BadRequestException(err.message ?? '文件上传失败'));
return;
}
next();
});
}
}