Add proxy downloads and bulk file operations

- Implement proxy download endpoint for better mobile Safari compatibility
- Add bulk selection with checkboxes in file browser
- Add bulk actions bar for downloading/deleting selected files
- Replace direct S3 downloads with server-proxied downloads
- Fix download issues on mobile devices by using proper link handling
This commit is contained in:
2025-06-04 18:37:41 +02:00
parent 1463fdb3d7
commit b7544d82f3
3 changed files with 190 additions and 16 deletions

View File

@@ -0,0 +1,56 @@
import { getDownloadUrl } from '~/server/utils/minio';
export default defineEventHandler(async (event) => {
try {
const query = getQuery(event);
const fileName = query.fileName as string;
if (!fileName) {
throw createError({
statusCode: 400,
statusMessage: 'File name is required',
});
}
// Get the download URL from MinIO
const url = await getDownloadUrl(fileName);
// Fetch the file from MinIO
const response = await fetch(url);
if (!response.ok) {
throw createError({
statusCode: response.status,
statusMessage: 'Failed to fetch file from storage',
});
}
// Get the file data
const arrayBuffer = await response.arrayBuffer();
const buffer = Buffer.from(arrayBuffer);
// Extract clean filename (remove timestamp prefix)
let cleanFileName = fileName.split('/').pop() || fileName;
const timestampMatch = cleanFileName.match(/^\d{10,}-(.+)$/);
if (timestampMatch) {
cleanFileName = timestampMatch[1];
}
// Get content type
const contentType = response.headers.get('content-type') || 'application/octet-stream';
// Set headers for download
setHeader(event, 'Content-Type', contentType);
setHeader(event, 'Content-Disposition', `attachment; filename="${cleanFileName}"`);
// Content-Length header is set automatically by Nitro when returning a buffer
// Return the file buffer
return buffer;
} catch (error: any) {
console.error('Failed to proxy download:', error);
throw createError({
statusCode: 500,
statusMessage: error.message || 'Failed to download file',
});
}
});