| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103 |
- import multer from 'multer';
- import path from 'path';
- import { v4 as uuidv4 } from 'uuid';
- import { config } from '../config/index.js';
- import { AppError } from './error.js';
- import { ERROR_CODES, HTTP_STATUS } from '@media-manager/shared';
- import fs from 'fs';
- // 确保上传目录存在
- const uploadDirs = ['videos', 'images', 'covers'];
- uploadDirs.forEach(dir => {
- const fullPath = path.join(config.upload.path, dir);
- if (!fs.existsSync(fullPath)) {
- try {
- fs.mkdirSync(fullPath, { recursive: true });
- } catch (err) {
- console.error(`[upload] Failed to create upload dir ${fullPath}:`, err);
- }
- }
- });
- // 视频存储配置
- const videoStorage = multer.diskStorage({
- destination: (_req, _file, cb) => {
- cb(null, path.join(config.upload.path, 'videos'));
- },
- filename: (_req, file, cb) => {
- const ext = path.extname(file.originalname);
- cb(null, `${uuidv4()}${ext}`);
- },
- });
- // 图片存储配置
- const imageStorage = multer.diskStorage({
- destination: (_req, _file, cb) => {
- cb(null, path.join(config.upload.path, 'images'));
- },
- filename: (_req, file, cb) => {
- const ext = path.extname(file.originalname);
- cb(null, `${uuidv4()}${ext}`);
- },
- });
- // 视频文件过滤
- const videoFilter = (_req: Express.Request, file: Express.Multer.File, cb: multer.FileFilterCallback) => {
- if (config.upload.allowedVideoTypes.includes(file.mimetype)) {
- cb(null, true);
- } else {
- cb(new AppError(
- '不支持的视频格式',
- HTTP_STATUS.BAD_REQUEST,
- ERROR_CODES.VIDEO_FORMAT_UNSUPPORTED
- ));
- }
- };
- // 图片文件过滤
- const imageFilter = (_req: Express.Request, file: Express.Multer.File, cb: multer.FileFilterCallback) => {
- if (config.upload.allowedImageTypes.includes(file.mimetype)) {
- cb(null, true);
- } else {
- cb(new AppError(
- '不支持的图片格式',
- HTTP_STATUS.BAD_REQUEST,
- ERROR_CODES.VALIDATION
- ));
- }
- };
- // 视频上传中间件
- export const uploadVideo = multer({
- storage: videoStorage,
- limits: {
- fileSize: config.upload.maxVideoSize,
- },
- fileFilter: videoFilter,
- }).single('video');
- // 图片上传中间件
- export const uploadImage = multer({
- storage: imageStorage,
- limits: {
- fileSize: config.upload.maxImageSize,
- },
- fileFilter: imageFilter,
- }).single('image');
- // 封面上传中间件
- export const uploadCover = multer({
- storage: multer.diskStorage({
- destination: (_req, _file, cb) => {
- cb(null, path.join(config.upload.path, 'covers'));
- },
- filename: (_req, file, cb) => {
- const ext = path.extname(file.originalname);
- cb(null, `${uuidv4()}${ext}`);
- },
- }),
- limits: {
- fileSize: config.upload.maxImageSize,
- },
- fileFilter: imageFilter,
- }).single('cover');
|