// ===================================================== // 個人頭像上傳 API // ===================================================== import { NextRequest, NextResponse } from 'next/server'; import { writeFile, mkdir } from 'fs/promises'; import { join } from 'path'; import { UserService } from '@/lib/services/database-service'; import { generateUniqueFileName, isValidImageType, isValidImageSize } from '@/lib/image-utils'; import sharp from 'sharp'; export async function POST(request: NextRequest) { try { const formData = await request.formData(); const file = formData.get('avatar') as File; const userId = formData.get('userId') as string; if (!file) { return NextResponse.json( { success: false, error: '請選擇要上傳的圖片' }, { status: 400 } ); } if (!userId) { return NextResponse.json( { success: false, error: '用戶ID不能為空' }, { status: 400 } ); } // 驗證文件類型 if (!isValidImageType(file)) { return NextResponse.json( { success: false, error: '只支援 JPEG、PNG、WebP 格式的圖片' }, { status: 400 } ); } // 驗證文件大小(限制 5MB) if (!isValidImageSize(file, 5)) { return NextResponse.json( { success: false, error: '圖片大小不能超過 5MB' }, { status: 400 } ); } // 創建上傳目錄 const uploadDir = join(process.cwd(), 'public', 'uploads', 'avatars'); await mkdir(uploadDir, { recursive: true }); // 生成唯一文件名 const fileName = generateUniqueFileName(file.name, userId); const filePath = join(uploadDir, fileName); // 讀取文件緩衝區 const bytes = await file.arrayBuffer(); const buffer = Buffer.from(bytes); // 使用 Sharp 優化圖片 const optimizedBuffer = await sharp(buffer) .resize(200, 200, { fit: 'cover', position: 'center' }) .jpeg({ quality: 85 }) .toBuffer(); // 保存優化後的圖片 await writeFile(filePath, optimizedBuffer); // 生成相對路徑(自動適應不同環境) const imageUrl = `/uploads/avatars/${fileName}`; // 更新用戶頭像 const userService = new UserService(); await userService.update(userId, { avatar: imageUrl }); console.log(`✅ 用戶 ${userId} 頭像上傳成功: ${imageUrl}`); return NextResponse.json({ success: true, message: '頭像上傳成功', data: { imageUrl, fileName, fileSize: optimizedBuffer.length, originalSize: file.size } }); } catch (error) { console.error('頭像上傳失敗:', error); return NextResponse.json( { success: false, error: '頭像上傳失敗', details: error instanceof Error ? error.message : '未知錯誤' }, { status: 500 } ); } }