feat: Implement file upload and management system
- Created database schema for files and file parts. - Added API endpoint to create a new file and generate an upload token. - Implemented API endpoint to complete file uploads and generate a download token. - Developed cron job for cleaning up expired files and deleting associated Discord messages. - Added API endpoint for soft deletion of files and their parts. - Implemented API endpoint to fetch file metadata and parts for download. - Created API endpoint to upload file parts to Discord. - Developed a client-side download page to handle file decryption and assembly. - Established database connection pooling for efficient database operations.
This commit is contained in:
64
src/app/api/upload-part/route.ts
Normal file
64
src/app/api/upload-part/route.ts
Normal file
@@ -0,0 +1,64 @@
|
||||
import { NextResponse } from 'next/server';
|
||||
import pool from '@/lib/db';
|
||||
|
||||
if (!process.env.DISCORD_WEBHOOK_URL) {
|
||||
throw new Error('Please define DISCORD_WEBHOOK_URL in .env.local');
|
||||
}
|
||||
|
||||
export async function POST(request: Request) {
|
||||
try {
|
||||
const formData = await request.formData();
|
||||
const fileId = formData.get('file_id') as string;
|
||||
const partIndex = formData.get('part_index') as string;
|
||||
const chunk = formData.get('encrypted_chunk') as Blob;
|
||||
|
||||
if (!fileId || !partIndex || !chunk) {
|
||||
return NextResponse.json({ error: 'Missing required form fields' }, { status: 400 });
|
||||
}
|
||||
|
||||
// Forward the chunk to Discord
|
||||
const discordFormData = new FormData();
|
||||
discordFormData.append('file', chunk, `chunk-${partIndex}.bin`);
|
||||
// You can add content to the message if you want
|
||||
// discordFormData.append('content', `File chunk for ${fileId}, part ${partIndex}`);
|
||||
|
||||
const discordRes = await fetch(process.env.DISCORD_WEBHOOK_URL, {
|
||||
method: 'POST',
|
||||
body: discordFormData,
|
||||
});
|
||||
|
||||
if (!discordRes.ok) {
|
||||
const errorBody = await discordRes.json();
|
||||
console.error('Discord API Error:', errorBody);
|
||||
return NextResponse.json({ error: 'Failed to upload to Discord' }, { status: 500 });
|
||||
}
|
||||
|
||||
const discordData = await discordRes.json();
|
||||
const attachment = discordData.attachments[0];
|
||||
|
||||
if (!attachment) {
|
||||
return NextResponse.json({ error: 'No attachment found in Discord response' }, { status: 500 });
|
||||
}
|
||||
|
||||
const discordMessageId = discordData.id;
|
||||
const discordAttachmentUrl = attachment.url;
|
||||
const partSize = attachment.size;
|
||||
|
||||
// Save part metadata to the database
|
||||
const connection = await pool.getConnection();
|
||||
try {
|
||||
await connection.query(
|
||||
'INSERT INTO file_parts (file_id, part_index, discord_message_id, discord_attachment_url, size) VALUES (?, ?, ?, ?, ?)',
|
||||
[fileId, parseInt(partIndex), discordMessageId, discordAttachmentUrl, partSize]
|
||||
);
|
||||
} finally {
|
||||
connection.release();
|
||||
}
|
||||
|
||||
return NextResponse.json({ success: true, part_index: partIndex });
|
||||
|
||||
} catch (error) {
|
||||
console.error('Error uploading part:', error);
|
||||
return NextResponse.json({ error: 'Internal Server Error' }, { status: 500 });
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user