added new zip download system

This commit is contained in:
averel10
2026-03-20 07:55:36 +01:00
parent c9080f3b3c
commit 815a509f4f
2 changed files with 73 additions and 22 deletions

View File

@@ -2,12 +2,46 @@ import { NextRequest, NextResponse } from 'next/server';
import { downloadFilteredEntries } from '@/app/actions/download-filtered-entries'; import { downloadFilteredEntries } from '@/app/actions/download-filtered-entries';
import JSZip from 'jszip'; import JSZip from 'jszip';
import { join } from 'path'; import { join } from 'path';
import { readFile, existsSync } from 'fs'; import { readFile, existsSync, writeFileSync, mkdirSync, readdirSync, unlinkSync, statSync } from 'fs';
import { promisify } from 'util'; import { promisify } from 'util';
import { requireAdmin } from '@/lib/auth'; import { requireAdmin } from '@/lib/auth';
const readFileAsync = promisify(readFile); const readFileAsync = promisify(readFile);
// Clean up old ZIP files older than 24 hours
async function cleanupOldZips(downloadsDir: string, maxAgeHours: number = 24) {
try {
if (!existsSync(downloadsDir)) {
return;
}
const files = readdirSync(downloadsDir);
const now = Date.now();
const maxAgeMs = maxAgeHours * 60 * 60 * 1000;
for (const file of files) {
if (!file.startsWith('dataset-') || !file.endsWith('.zip')) {
continue;
}
const filePath = join(downloadsDir, file);
try {
const stats = statSync(filePath);
const fileAge = now - stats.mtimeMs;
if (fileAge > maxAgeMs) {
unlinkSync(filePath);
console.log(`Cleaned up old ZIP file: ${file} (age: ${(fileAge / (60 * 60 * 1000)).toFixed(1)} hours)`);
}
} catch (error) {
console.error(`Error cleaning up file ${file}:`, error);
}
}
} catch (error) {
console.error('Error during cleanup:', error);
}
}
interface FilterParams { interface FilterParams {
speakerId?: string; speakerId?: string;
modelName?: string; modelName?: string;
@@ -84,16 +118,37 @@ export async function POST(request: NextRequest) {
// Generate ZIP blob // Generate ZIP blob
const zipBuffer = await zip.generateAsync({ type: 'nodebuffer' }); const zipBuffer = await zip.generateAsync({ type: 'nodebuffer' });
// Create response with ZIP file // Save ZIP to public folder
const fileName = `dataset-${datasetId}-export-${new Date().toISOString().split('T')[0]}.zip`; const downloadsDir = join(process.cwd(), 'public', 'downloads');
// Ensure downloads directory exists
try {
mkdirSync(downloadsDir, { recursive: true });
} catch (error) {
console.error('Error creating downloads directory:', error);
}
return new NextResponse(new Uint8Array(zipBuffer), { // Create filename with timestamp for uniqueness
status: 200, const timestamp = Date.now();
headers: { const fileName = `dataset-${datasetId}-export-${new Date().toISOString().split('T')[0]}-${timestamp}.zip`;
'Content-Type': 'application/zip', const filePath = join(downloadsDir, fileName);
'Content-Disposition': `attachment; filename="${fileName}"`,
'Content-Length': zipBuffer.length.toString(), // Write ZIP file to disk
}, writeFileSync(filePath, zipBuffer);
console.log(`ZIP file saved to: ${filePath}`);
// Clean up old ZIP files in the background
cleanupOldZips(downloadsDir).catch(error => {
console.error('Cleanup failed:', error);
});
// Return download URL
const downloadUrl = `/downloads/${fileName}`;
return NextResponse.json({
success: true,
downloadUrl,
fileName,
}); });
} catch (error) { } catch (error) {
console.error('Error creating ZIP:', error); console.error('Error creating ZIP:', error);

View File

@@ -24,21 +24,17 @@ export async function downloadFilteredEntriesAsZip(
if (!response.ok) { if (!response.ok) {
const errorData = await response.json(); const errorData = await response.json();
throw new Error(errorData.error || 'Failed to download ZIP'); throw new Error(errorData.error || 'Failed to prepare ZIP');
} }
// Get the ZIP blob from response const data = await response.json();
const blob = await response.blob();
if (!data.success || !data.downloadUrl) {
throw new Error('Invalid response from server');
}
// Trigger download // Redirect to the generated ZIP file
const url = URL.createObjectURL(blob); window.location.href = data.downloadUrl;
const a = document.createElement('a');
a.href = url;
a.download = `dataset-${datasetId}-export-${new Date().toISOString().split('T')[0]}.zip`;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(url);
} catch (error) { } catch (error) {
console.error('Error downloading ZIP:', error); console.error('Error downloading ZIP:', error);
throw error; throw error;