檔案上傳新增至資料庫
This commit is contained in:
140
app/api/upload/route.ts
Normal file
140
app/api/upload/route.ts
Normal file
@@ -0,0 +1,140 @@
|
||||
import { NextRequest, NextResponse } from 'next/server';
|
||||
import { writeFile, mkdir } from 'fs/promises';
|
||||
import { ProjectService, ProjectFileService, CriteriaItemService } from '@/lib/services/database';
|
||||
import {
|
||||
getUploadAbsolutePath,
|
||||
getUploadRelativePath,
|
||||
getUploadDirPath,
|
||||
generateUniqueFileName,
|
||||
isValidFileType,
|
||||
isValidFileSize
|
||||
} from '@/lib/utils/file-path';
|
||||
|
||||
export async function POST(request: NextRequest) {
|
||||
try {
|
||||
const formData = await request.formData();
|
||||
const projectTitle = formData.get('projectTitle') as string;
|
||||
const projectDescription = formData.get('projectDescription') as string;
|
||||
const file = formData.get('file') as File;
|
||||
|
||||
console.log('🚀 開始處理檔案上傳...');
|
||||
console.log('📝 專案標題:', projectTitle);
|
||||
console.log('📋 專案描述:', projectDescription);
|
||||
console.log('📁 上傳文件:', file ? file.name : '無');
|
||||
|
||||
// 驗證必填欄位
|
||||
if (!projectTitle?.trim()) {
|
||||
return NextResponse.json(
|
||||
{ success: false, error: '請填寫專案標題' },
|
||||
{ status: 400 }
|
||||
);
|
||||
}
|
||||
|
||||
if (!file) {
|
||||
return NextResponse.json(
|
||||
{ success: false, error: '請上傳文件' },
|
||||
{ status: 400 }
|
||||
);
|
||||
}
|
||||
|
||||
// 驗證檔案類型
|
||||
if (!isValidFileType(file.type)) {
|
||||
return NextResponse.json(
|
||||
{ success: false, error: '不支援的檔案類型' },
|
||||
{ status: 400 }
|
||||
);
|
||||
}
|
||||
|
||||
// 驗證檔案大小(100MB)
|
||||
if (!isValidFileSize(file.size, 100)) {
|
||||
return NextResponse.json(
|
||||
{ success: false, error: '檔案大小超過 100MB 限制' },
|
||||
{ status: 400 }
|
||||
);
|
||||
}
|
||||
|
||||
// 獲取預設評分標準模板
|
||||
const templates = await CriteriaItemService.getAllTemplates();
|
||||
if (!templates || templates.length === 0) {
|
||||
return NextResponse.json(
|
||||
{ success: false, error: '未找到評分標準,請先設定評分標準' },
|
||||
{ status: 400 }
|
||||
);
|
||||
}
|
||||
|
||||
const templateId = templates[0].id;
|
||||
console.log('📊 使用評分標準模板 ID:', templateId);
|
||||
|
||||
// 創建專案記錄
|
||||
const projectData = {
|
||||
user_id: 1, // 暫時使用固定用戶 ID
|
||||
template_id: templateId,
|
||||
title: projectTitle,
|
||||
description: projectDescription || null,
|
||||
status: 'uploading' as const, // 初始狀態為上傳中
|
||||
analysis_started_at: null,
|
||||
analysis_completed_at: null
|
||||
};
|
||||
|
||||
console.log('💾 創建專案記錄...');
|
||||
const projectResult = await ProjectService.create(projectData);
|
||||
const projectId = (projectResult as any).insertId;
|
||||
console.log('✅ 專案記錄創建成功,ID:', projectId);
|
||||
|
||||
// 準備檔案儲存
|
||||
const uploadDir = getUploadDirPath(projectId);
|
||||
await mkdir(uploadDir, { recursive: true });
|
||||
|
||||
// 生成唯一檔案名稱
|
||||
const uniqueFileName = generateUniqueFileName(file.name);
|
||||
const filePath = getUploadAbsolutePath(projectId, uniqueFileName);
|
||||
const relativeFilePath = getUploadRelativePath(projectId, uniqueFileName);
|
||||
|
||||
// 儲存檔案
|
||||
console.log('💾 儲存檔案到:', filePath);
|
||||
console.log('📁 相對路徑:', relativeFilePath);
|
||||
const bytes = await file.arrayBuffer();
|
||||
await writeFile(filePath, Buffer.from(bytes));
|
||||
|
||||
// 創建檔案記錄
|
||||
const fileExtension = file.name.split('.').pop();
|
||||
const fileData = {
|
||||
project_id: projectId,
|
||||
original_name: file.name,
|
||||
file_name: uniqueFileName,
|
||||
file_path: relativeFilePath, // 使用相對路徑
|
||||
file_size: file.size,
|
||||
file_type: fileExtension || '',
|
||||
mime_type: file.type,
|
||||
upload_status: 'completed' as const,
|
||||
upload_progress: 100
|
||||
};
|
||||
|
||||
console.log('💾 創建檔案記錄...');
|
||||
await ProjectFileService.create(fileData);
|
||||
console.log('✅ 檔案記錄創建成功');
|
||||
|
||||
// 更新專案狀態為 completed(檔案上傳完成)
|
||||
console.log('🔄 更新專案狀態為 completed...');
|
||||
await ProjectService.update(projectId, { status: 'completed' });
|
||||
console.log('✅ 專案狀態更新完成');
|
||||
|
||||
return NextResponse.json({
|
||||
success: true,
|
||||
data: {
|
||||
projectId,
|
||||
fileName: file.name,
|
||||
fileSize: file.size,
|
||||
fileType: file.type
|
||||
},
|
||||
message: '檔案上傳成功'
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ 檔案上傳失敗:', error);
|
||||
return NextResponse.json(
|
||||
{ success: false, error: '檔案上傳失敗,請稍後再試' },
|
||||
{ status: 500 }
|
||||
);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user