Files
2025-09-21 22:11:20 +08:00

104 lines
2.9 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// =====================================================
// 個人頭像上傳 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 }
);
}
}