Add proxy endpoint to fix CORS issues for file previews

- Create new `/api/files/proxy-preview` endpoint that fetches and serves files directly
- Update FilePreviewModal to use proxy endpoint for images and PDFs
- Set appropriate headers for inline display and caching
- Remove trailing slash from folder display names in file list
This commit is contained in:
Matt 2025-06-04 17:19:52 +02:00
parent 7d5b39b29d
commit 9e9c667d1f
3 changed files with 59 additions and 7 deletions

View File

@ -155,13 +155,16 @@ const loadPreview = async () => {
previewUrl.value = '';
try {
const response = await $fetch('/api/files/preview', {
params: { fileName: props.file.name },
});
previewUrl.value = response.url;
// For images and PDFs, use the proxy endpoint to avoid CORS issues
if (isImage.value || isPdf.value) {
// Use the proxy endpoint that serves the file directly
previewUrl.value = `/api/files/proxy-preview?fileName=${encodeURIComponent(props.file.name)}`;
// The loading state will be handled by the image/iframe onload event
} else {
throw new Error('File type does not support preview');
}
} catch (err: any) {
error.value = err.data?.statusMessage || 'Failed to load preview';
error.value = err.data?.statusMessage || err.message || 'Failed to load preview';
loading.value = false;
}
};

View File

@ -81,7 +81,7 @@ function getDisplayName(filepath: string): string {
// Handle folders (ending with /)
if (filepath.endsWith('/')) {
const parts = filepath.slice(0, -1).split('/');
return parts[parts.length - 1] + '/';
return parts[parts.length - 1]; // Return folder name without trailing slash
}
// Get just the filename from the full path

View File

@ -0,0 +1,49 @@
import { getDownloadUrl } from '~/server/utils/minio';
import mime from 'mime-types';
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 content type
const contentType = mime.lookup(fileName) || 'application/octet-stream';
// Get the download URL
const url = await getDownloadUrl(fileName);
// Fetch the file content 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 buffer
const buffer = Buffer.from(await response.arrayBuffer());
// Set appropriate headers for preview
setHeader(event, 'Content-Type', contentType);
setHeader(event, 'Content-Disposition', 'inline');
setHeader(event, 'Cache-Control', 'public, max-age=3600');
// Return the file buffer
return buffer;
} catch (error: any) {
console.error('Failed to proxy preview:', error);
throw createError({
statusCode: 500,
statusMessage: error.message || 'Failed to proxy preview',
});
}
});