const EXT_MIME: Record = { pdf: 'application/pdf', png: 'image/png', jpg: 'image/jpeg', jpeg: 'image/jpeg', gif: 'image/gif', webp: 'image/webp', bmp: 'image/bmp', svg: 'image/svg+xml', mp4: 'video/mp4', mov: 'video/quicktime', avi: 'video/x-msvideo', webm: 'video/webm', mkv: 'video/x-matroska', m4v: 'video/x-m4v', wmv: 'video/x-ms-wmv', xlsx: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', xls: 'application/vnd.ms-excel', csv: 'text/csv', docx: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', doc: 'application/msword', pptx: 'application/vnd.openxmlformats-officedocument.presentationml.presentation', ppt: 'application/vnd.ms-powerpoint', hwp: 'application/x-hwp', hwpx: 'application/hwp+zip', txt: 'text/plain', }; /** multer가 application/octet-stream 으로 저장할 때 확장자로 보정 */ export function resolveFileMime(originalName: string, stored?: string | null): string { const ext = originalName.split('.').pop()?.toLowerCase() ?? ''; const fromExt = ext ? EXT_MIME[ext] : undefined; if (!stored || stored === 'application/octet-stream' || stored === 'application/x-msdownload') { return fromExt ?? stored ?? 'application/octet-stream'; } if (fromExt && stored.startsWith('application/') && stored.includes('octet')) { return fromExt; } return stored; } export function isInlinePreviewMime(mime: string): boolean { return ( mime.startsWith('image/') || mime.startsWith('video/') || mime.startsWith('text/') || mime === 'application/pdf' || mime.includes('spreadsheet') || mime.includes('excel') || mime.includes('wordprocessingml') || mime.includes('presentationml') || mime === 'application/msword' || mime === 'application/vnd.ms-powerpoint' || mime === 'application/x-hwp' || mime === 'application/hwp+zip' ); }