// app/api/upload-attachment/route.ts import { NextRequest, NextResponse } from 'next/server' import { writeFile, mkdir } from 'fs/promises' import { join } from 'path' import { randomUUID } from 'crypto' import db from '@/db/db' import { vendorEvaluationAttachments } from '@/db/schema' export async function POST(request: NextRequest) { try { const formData = await request.formData() const files = formData.getAll('files') as File[] const submissionId = formData.get('submissionId') as string const responseId = formData.get('responseId') as string const uploadedBy = formData.get('uploadedBy') as string if (!files || files.length === 0) { return NextResponse.json({ error: '파일이 선택되지 않았습니다.' }, { status: 400 }) } if (!submissionId || !responseId || !uploadedBy) { return NextResponse.json({ error: '필수 매개변수가 누락되었습니다.' }, { status: 400 }) } const uploadedFiles = [] // uploads 디렉토리 생성 (없는 경우) const uploadsDir = join(process.cwd(), 'public', 'uploads', 'attachments') try { await mkdir(uploadsDir, { recursive: true }) } catch (error) { // 디렉토리가 이미 존재하는 경우 무시 } for (const file of files) { // 파일 검증 if (file.size > 10 * 1024 * 1024) { // 10MB 제한 return NextResponse.json({ error: `파일 ${file.name}이 너무 큽니다. (최대 10MB)` }, { status: 400 }) } // 파일 확장자 검증 (선택적) const allowedTypes = [ 'image/jpeg', 'image/png', 'image/gif', 'image/webp', 'application/pdf', 'application/msword', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', 'application/vnd.ms-excel', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', 'text/plain', 'text/csv' ] if (!allowedTypes.includes(file.type)) { return NextResponse.json({ error: `지원되지 않는 파일 형식입니다: ${file.name}` }, { status: 400 }) } // 고유한 파일명 생성 const fileExtension = file.name.split('.').pop() || '' const storedFileName = `${randomUUID()}.${fileExtension}` const filePath = join('uploads', 'attachments', storedFileName) const fullPath = join(process.cwd(), 'public', filePath) try { // 파일 저장 const bytes = await file.arrayBuffer() const buffer = Buffer.from(bytes) await writeFile(fullPath, buffer) // 데이터베이스에 파일 정보 저장 const [savedAttachment] = await db .insert(vendorEvaluationAttachments) .values({ submissionId: parseInt(submissionId), generalEvaluationResponseId: parseInt(responseId), originalFileName: file.name, storedFileName: storedFileName, filePath: filePath, fileSize: file.size, mimeType: file.type, uploadedBy: uploadedBy, isActive: true, }) .returning() uploadedFiles.push({ id: savedAttachment.id, fileId: savedAttachment.fileId, originalFileName: savedAttachment.originalFileName, fileSize: savedAttachment.fileSize, mimeType: savedAttachment.mimeType, }) } catch (fileError) { console.error(`파일 저장 실패: ${file.name}`, fileError) return NextResponse.json({ error: `파일 저장에 실패했습니다: ${file.name}` }, { status: 500 }) } } return NextResponse.json({ success: true, files: uploadedFiles, message: `${uploadedFiles.length}개 파일이 성공적으로 업로드되었습니다.` }) } catch (error) { console.error('파일 업로드 오류:', error) return NextResponse.json({ error: '파일 업로드에 실패했습니다.' }, { status: 500 }) } }