94 lines
3.0 KiB
TypeScript
94 lines
3.0 KiB
TypeScript
import { NextResponse } from "next/server";
|
||
import { z } from "zod";
|
||
|
||
import { auth } from "@/app/(auth)/auth";
|
||
import { uploadFile } from "@/lib/storage/service";
|
||
|
||
// Use Blob instead of File since File is not available in Node.js environment
|
||
const FileSchema = z.object({
|
||
file: z
|
||
.instanceof(Blob)
|
||
.refine((file) => file.size <= 8 * 1024 * 1024, {
|
||
message: "File size should be less than 8MB",
|
||
})
|
||
// Update the file type based on the kind of files you want to accept
|
||
.refine((file) => ["image/jpeg", "image/png", "image/webp"].includes(file.type), {
|
||
message: "File type should be JPEG, PNG or WebP",
|
||
}),
|
||
});
|
||
|
||
export async function POST(request: Request) {
|
||
console.log("[Upload API] Received upload request");
|
||
|
||
const session = await auth();
|
||
|
||
if (!session) {
|
||
console.log("[Upload API] Unauthorized - no session");
|
||
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
|
||
}
|
||
|
||
if (request.body === null) {
|
||
console.log("[Upload API] Request body is empty");
|
||
return new Response("Request body is empty", { status: 400 });
|
||
}
|
||
|
||
try {
|
||
const formData = await request.formData();
|
||
const file = formData.get("file") as Blob;
|
||
|
||
console.log("[Upload API] FormData received, file exists:", !!file);
|
||
|
||
if (!file) {
|
||
console.log("[Upload API] No file in FormData");
|
||
return NextResponse.json({ error: "No file uploaded" }, { status: 400 });
|
||
}
|
||
|
||
console.log("[Upload API] File info:", {
|
||
type: file.type,
|
||
size: file.size,
|
||
sizeInMB: (file.size / 1024 / 1024).toFixed(2) + "MB"
|
||
});
|
||
|
||
const validatedFile = FileSchema.safeParse({ file });
|
||
|
||
if (!validatedFile.success) {
|
||
const errorMessage = validatedFile.error.errors
|
||
.map((error) => error.message)
|
||
.join(", ");
|
||
|
||
console.log("[Upload API] Validation failed:", errorMessage);
|
||
return NextResponse.json({ error: errorMessage }, { status: 400 });
|
||
}
|
||
|
||
// Get filename from formData since Blob doesn't have name property
|
||
const filename = (formData.get("file") as File).name;
|
||
console.log("[Upload API] Filename:", filename);
|
||
|
||
const fileBuffer = await file.arrayBuffer();
|
||
console.log("[Upload API] File buffer size:", fileBuffer.byteLength);
|
||
|
||
try {
|
||
// 使用统一的存储服务(支持数据库配置的 S3、环境变量 S3 或 Vercel Blob)
|
||
const data = await uploadFile(filename, fileBuffer);
|
||
|
||
console.log("[Upload API] Upload successful:", data.url);
|
||
return NextResponse.json(data);
|
||
} catch (_error) {
|
||
console.error("[Upload API] Upload failed:", _error);
|
||
return NextResponse.json({
|
||
error: "Upload failed",
|
||
details: _error instanceof Error ? _error.message : String(_error)
|
||
}, { status: 500 });
|
||
}
|
||
} catch (_error) {
|
||
console.error("[Upload API] Request processing failed:", _error);
|
||
return NextResponse.json(
|
||
{
|
||
error: "Failed to process request",
|
||
details: _error instanceof Error ? _error.message : String(_error)
|
||
},
|
||
{ status: 500 }
|
||
);
|
||
}
|
||
}
|