WuYongJie d1c6efc79d
Some checks failed
CI Check / check (push) Has been cancelled
feat: NAS 部署与 Harbor 推送流程
2025-12-03 14:39:06 +08:00

87 lines
2.4 KiB
TypeScript
Raw 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
*
* POST: 上传用户头像
*
* @created 2025-11-25
* @api
*/
import { NextRequest, NextResponse } from 'next/server'
import { getServerSession } from 'next-auth'
import { authOptions } from '@/lib/auth'
import { prisma } from '@/lib/prisma'
import { uploadToS3 } from '@/lib/s3'
import { processImage, getProcessedFileName } from '@/lib/image-processor'
import path from 'path'
export async function POST(req: NextRequest) {
try {
const session = await getServerSession(authOptions)
if (!session?.user?.id) {
return NextResponse.json(
{ error: '未登录' },
{ status: 401 }
)
}
const formData = await req.formData()
const avatarFile = formData.get('avatar') as File
if (!avatarFile) {
return NextResponse.json(
{ error: '请选择头像文件' },
{ status: 400 }
)
}
// 验证文件类型
const allowedImageTypes = ['image/jpeg', 'image/jpg', 'image/png', 'image/webp']
if (!allowedImageTypes.includes(avatarFile.type)) {
return NextResponse.json(
{ error: '不支持的图片格式,请使用 JPG、PNG 或 WebP 格式' },
{ status: 400 }
)
}
// 验证文件大小(限制5MB)
const maxSize = 5 * 1024 * 1024 // 5MB
if (avatarFile.size > maxSize) {
return NextResponse.json(
{ error: `头像过大,请使用小于5MB的图片(当前:${(avatarFile.size / 1024 / 1024).toFixed(2)}MB)` },
{ status: 400 }
)
}
// 处理头像:压缩并转换为webP
const originalBuffer = Buffer.from(await avatarFile.arrayBuffer())
const processedBuffer = await processImage(originalBuffer, {
maxSizeKB: 200,
maxWidth: 400,
maxHeight: 400,
format: 'webp',
})
// 上传到S3
const processedFileName = getProcessedFileName(avatarFile.name)
const fileExt = path.extname(processedFileName)
const avatarFileName = `avatar-${session.user.id}-${Date.now()}${fileExt}`
const avatarUrl = await uploadToS3(processedBuffer, avatarFileName, 'image/webp')
// 更新数据库
await prisma.user.update({
where: { id: session.user.id },
data: { avatar: avatarUrl },
})
return NextResponse.json({ avatarUrl })
} catch (error) {
console.error('[UserAvatar] POST error:', error)
return NextResponse.json(
{ error: '上传头像失败' },
{ status: 500 }
)
}
}