summaryrefslogtreecommitdiff
path: root/frontend/app/api
diff options
context:
space:
mode:
authordiogo464 <[email protected]>2025-08-11 13:40:27 +0100
committerdiogo464 <[email protected]>2025-08-11 13:40:27 +0100
commitf69ca010b80703389fffe75fc6dca907e53df74d (patch)
tree1cf081f49b3793aae3f298ed50753841fd306424 /frontend/app/api
parent4af66f418b6837b6441b4e8eaf2d8ede585238b9 (diff)
basic file upload
Diffstat (limited to 'frontend/app/api')
-rw-r--r--frontend/app/api/upload/route.ts127
1 files changed, 127 insertions, 0 deletions
diff --git a/frontend/app/api/upload/route.ts b/frontend/app/api/upload/route.ts
new file mode 100644
index 0000000..eb1ecaa
--- /dev/null
+++ b/frontend/app/api/upload/route.ts
@@ -0,0 +1,127 @@
1import { NextRequest, NextResponse } from 'next/server'
2import { writeFile, unlink } from 'fs/promises'
3import { tmpdir } from 'os'
4import { join } from 'path'
5import { randomUUID } from 'crypto'
6import { Auth_get_user, Auth_user_can_upload } from '@/lib/auth'
7import { Drive_import } from '@/lib/drive'
8import { UPLOAD_MAX_FILE_SIZE, UPLOAD_MAX_FILES } from '@/lib/constants'
9import { revalidatePath } from 'next/cache'
10
11export async function POST(request: NextRequest) {
12 try {
13 // Check user authentication and permissions
14 const user = await Auth_get_user()
15 if (!user.isLoggedIn) {
16 return NextResponse.json({ error: 'User not authenticated' }, { status: 401 })
17 }
18
19 if (!Auth_user_can_upload(user)) {
20 return NextResponse.json({ error: 'User does not have upload permissions' }, { status: 403 })
21 }
22
23 // Parse form data
24 const formData = await request.formData()
25 const files = formData.getAll('files') as File[]
26 const targetPath = formData.get('targetPath') as string || ''
27
28 // Validate files
29 if (!files || files.length === 0) {
30 return NextResponse.json({ error: 'No files provided' }, { status: 400 })
31 }
32
33 if (files.length > UPLOAD_MAX_FILES) {
34 return NextResponse.json({
35 error: `Too many files. Maximum ${UPLOAD_MAX_FILES} files allowed`
36 }, { status: 400 })
37 }
38
39 // Validate each file
40 for (const file of files) {
41 if (file.size > UPLOAD_MAX_FILE_SIZE) {
42 return NextResponse.json({
43 error: `File '${file.name}' exceeds maximum size of ${UPLOAD_MAX_FILE_SIZE / (1024 * 1024)}MB`
44 }, { status: 400 })
45 }
46 }
47
48 const uploadResults = []
49 const tempFiles: string[] = []
50
51 try {
52 // Process each file
53 for (const file of files) {
54 // Create temporary file
55 const tempFileName = `${randomUUID()}-${file.name}`
56 const tempFilePath = join(tmpdir(), tempFileName)
57 tempFiles.push(tempFilePath)
58
59 // Save file to temporary location
60 const bytes = await file.arrayBuffer()
61 const buffer = Buffer.from(bytes)
62 await writeFile(tempFilePath, buffer)
63
64 // Determine target drive path
65 const driveFilePath = targetPath ? `${targetPath}/${file.name}` : `/${file.name}`
66
67 try {
68 // Import file using Drive_import
69 await Drive_import(tempFilePath, driveFilePath, user.email)
70 uploadResults.push({
71 filename: file.name,
72 success: true,
73 message: 'File uploaded successfully'
74 })
75 } catch (error) {
76 console.error(`Failed to import file ${file.name}:`, error)
77 uploadResults.push({
78 filename: file.name,
79 success: false,
80 message: error instanceof Error ? error.message : 'Unknown error during import'
81 })
82 }
83 }
84
85 // Clean up temporary files
86 for (const tempFile of tempFiles) {
87 try {
88 await unlink(tempFile)
89 } catch (error) {
90 console.error(`Failed to delete temp file ${tempFile}:`, error)
91 }
92 }
93
94 // Revalidate the target path to refresh the directory listing
95 revalidatePath(`/drive${targetPath}`)
96 revalidatePath('/drive')
97
98 // Check if any uploads succeeded
99 const successfulUploads = uploadResults.filter(result => result.success)
100 const failedUploads = uploadResults.filter(result => !result.success)
101
102 return NextResponse.json({
103 success: true,
104 message: `${successfulUploads.length} files uploaded successfully${failedUploads.length > 0 ? `, ${failedUploads.length} failed` : ''}`,
105 results: uploadResults
106 })
107
108 } catch (error) {
109 // Clean up temporary files on error
110 for (const tempFile of tempFiles) {
111 try {
112 await unlink(tempFile)
113 } catch (cleanupError) {
114 console.error(`Failed to delete temp file during cleanup ${tempFile}:`, cleanupError)
115 }
116 }
117 throw error
118 }
119
120 } catch (error) {
121 console.error('Upload error:', error)
122 return NextResponse.json(
123 { error: error instanceof Error ? error.message : 'Internal server error' },
124 { status: 500 }
125 )
126 }
127} \ No newline at end of file