You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
70 lines
1.8 KiB
70 lines
1.8 KiB
import multer from 'multer';
|
|
import fs from 'node:fs';
|
|
import path from 'node:path';
|
|
import { callNodeListener } from 'h3';
|
|
import {
|
|
RELATIVE_ASSETS_DIR,
|
|
POST_MEDIA_PUBLIC_PREFIX,
|
|
ALLOWED_MIME_TYPES,
|
|
MAX_FILE_SIZE,
|
|
MAX_FILE_COUNT,
|
|
} from '#server/constants/upload';
|
|
import { getContextUser } from '#server/utils/context';
|
|
|
|
interface IFile {
|
|
name: string;
|
|
url: string;
|
|
mimeType: string;
|
|
size: number;
|
|
}
|
|
|
|
export default defineWrappedResponseHandler({ auth: 'required' }, async (event) => {
|
|
const user = getContextUser(event)!;
|
|
|
|
const uploadDir = path.resolve(RELATIVE_ASSETS_DIR);
|
|
|
|
if (!fs.existsSync(uploadDir)) {
|
|
fs.mkdirSync(uploadDir, { recursive: true });
|
|
}
|
|
|
|
const storage = multer.diskStorage({
|
|
destination: uploadDir,
|
|
filename: (_req, file, cb) => {
|
|
const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1e9);
|
|
const ext = path.extname(file.originalname).toLowerCase();
|
|
const baseName = path.basename(file.originalname, ext).replace(/[^a-z0-9]/gi, '-');
|
|
cb(null, `${uniqueSuffix}-${baseName}${ext}`);
|
|
},
|
|
});
|
|
|
|
const upload = multer({
|
|
storage,
|
|
limits: { fileSize: MAX_FILE_SIZE },
|
|
fileFilter: (_req, file, cb) => {
|
|
if ((ALLOWED_MIME_TYPES as readonly string[]).includes(file.mimetype)) {
|
|
cb(null, true);
|
|
} else {
|
|
cb(new Error('只支持 PNG/JPG/WebP 格式图片'));
|
|
}
|
|
},
|
|
});
|
|
|
|
await callNodeListener(
|
|
// @ts-expect-error Nuxt 类型兼容
|
|
upload.array('file', MAX_FILE_COUNT),
|
|
event.node.req,
|
|
event.node.res,
|
|
);
|
|
|
|
// @ts-expect-error
|
|
const uploadedFiles = event.node.req.files || [];
|
|
|
|
const result: IFile[] = uploadedFiles.map((file: any) => ({
|
|
name: file.originalname,
|
|
url: `${POST_MEDIA_PUBLIC_PREFIX}${file.filename}`,
|
|
mimeType: file.mimetype,
|
|
size: file.size,
|
|
}));
|
|
|
|
return result;
|
|
});
|
|
|