lifetracker/apps/web/app/api/db/upload/route.ts

64 lines
2.4 KiB
TypeScript

import { NextRequest, NextResponse } from 'next/server';
import fs from 'fs';
import path from 'path';
import serverConfig from '@lifetracker/shared/config';
// Define paths for uploaded files and the production DB
const UPLOAD_DIR = path.join(process.cwd(), 'uploads');
const DB_PATH = path.join(serverConfig.dataDir, 'lifetracker.db');
// Ensure upload directory exists
if (!fs.existsSync(UPLOAD_DIR)) {
fs.mkdirSync(UPLOAD_DIR, { recursive: true });
}
export async function POST(req: NextRequest) {
try {
const contentType = req.headers.get('content-type') || '';
if (!contentType.includes('multipart/form-data')) {
return NextResponse.json({ message: 'Invalid content type. Please upload a file.' }, { status: 400 });
}
// Create a writable stream for saving the uploaded file
const formBoundary = contentType.split('boundary=')[1];
const formData = req.body;
// Parse and save the uploaded file
const chunks: Buffer[] = [];
for await (const chunk of formData) {
chunks.push(chunk);
}
const bodyBuffer = Buffer.concat(chunks);
const start = bodyBuffer.indexOf(`\r\n\r\n`) + 4;
const end = bodyBuffer.indexOf(`\r\n--${formBoundary}`, start);
const fileContent = bodyBuffer.slice(start, end);
// Save the uploaded file to the upload directory
const uploadedFilePath = path.join(UPLOAD_DIR, 'uploaded.db');
fs.writeFileSync(uploadedFilePath, fileContent);
// Validate the uploaded file extension
if (!uploadedFilePath.endsWith('.db')) {
return NextResponse.json({ message: 'Invalid file type. Please upload a .db file.' }, { status: 400 });
}
// Backup the current production database
const backupPath = path.join(
serverConfig.dataDir,
`backup_${Date.now()}.db`
);
if (fs.existsSync(DB_PATH)) {
fs.copyFileSync(DB_PATH, backupPath);
}
// Replace the production database with the uploaded file
fs.renameSync(uploadedFilePath, DB_PATH);
return NextResponse.json({ message: 'Database uploaded and replaced successfully!' }, { status: 200 });
} catch (error) {
console.error('Error handling the uploaded file:', error);
return NextResponse.json({ message: 'Error processing upload.' }, { status: 500 });
}
}