Public Source Viewer

비나래아카이브 개발자 포털

실제 서비스 구조를 살펴볼 수 있는 공개용 코드 뷰어입니다. 인증, 세션, 외부 연동, 토큰, 관리자 식별 등 보안상 민감한 구현은 파일 단위 또는 줄 단위로 검열됩니다.

Redacted View
src/config/multer.config.ts
공개 가능
1 import multer from 'multer';
2 import path from 'path';
3 import { randomUUID } from 'crypto';
4 import { PUBLIC_DIR } from '../utils/paths';
5
6 const IMAGE_EXTENSIONS = new Set(['.jpg', '.jpeg', '.png', '.gif', '.webp']);
7 const IMAGE_MIME_TYPES = new Set(['image/jpeg', 'image/png', 'image/gif', 'image/webp']);
8
9 function imageFileFilter(_req: Express.Request, file: Express.Multer.File, cb: multer.FileFilterCallback): void {
10 const extension = path.extname(file.originalname).toLowerCase();
11 if (IMAGE_EXTENSIONS.has(extension) && IMAGE_MIME_TYPES.has(file.mimetype)) return cb(null, true);
12 cb(new Error('JPG, PNG, GIF 또는 WEBP 이미지만 업로드할 수 있습니다.'));
13 }
14
15 export const storage = multer.diskStorage({
16 destination: function (req, file, cb) {
17 cb(null, path.join(PUBLIC_DIR, 'uploads'));
18 },
19 filename: function (req, file, cb) {
20 cb(null, `${Date.now()}-${randomUUID()}${path.extname(file.originalname).toLowerCase()}`);
21 }
22 });
23
24 export const upload = multer({
25 storage,
26 fileFilter: imageFileFilter,
27 limits: { fileSize: 20 * 1024 * 1024, files: 1 }
28 });
29
30 const profileStorage = multer.diskStorage({
31 destination: function (req, file, cb) {
32 cb(null, path.join(PUBLIC_DIR, 'uploads', 'profiles'));
33 },
34 filename: function (req, file, cb) {
35 const username = (req as any).session?.username || 'unknown';
36 cb(null, `${username}_${Date.now()}${path.extname(file.originalname)}`);
37 }
38 });
39
40 export const profileUpload = multer({
41 storage: profileStorage,
42 fileFilter: (req, file, cb) => {
43 if (/\.(jpg|jpeg|png|gif|webp)$/i.test(path.extname(file.originalname))) {
44 cb(null, true);
45 } else {
46 cb(new Error('이미지 파일만 업로드 가능합니다.'));
47 }
48 },
49 limits: { fileSize: 2 * 1024 * 1024 }
50 });
51
52 export const memoryUpload = multer({
53 storage: multer.memoryStorage(),
54 fileFilter: (req, file, cb) => {
55 if (/\.(jpg|jpeg|png|gif|webp)$/i.test(path.extname(file.originalname))) {
56 cb(null, true);
57 } else {
58 cb(new Error('이미지 파일만 업로드 가능합니다.'));
59 }
60 },
61 limits: { fileSize: 10 * 1024 * 1024 }
62 });
63