65 lines
2.0 KiB
TypeScript
65 lines
2.0 KiB
TypeScript
import { NextRequest, NextResponse } from 'next/server';
|
|
import { localStorage } from '@/lib/local-storage';
|
|
import path from 'path';
|
|
|
|
export async function GET(request: NextRequest, { params }: { params: Promise<{ path: string[] }> }) {
|
|
try {
|
|
const { path: pathSegments } = await params;
|
|
const filePath = normalizeStoragePath(pathSegments.join('/'));
|
|
if (!filePath) {
|
|
return NextResponse.json({ error: 'Invalid file path' }, { status: 400 });
|
|
}
|
|
|
|
if (!localStorage.fileExists(filePath)) {
|
|
return NextResponse.json({ error: 'File not found' }, { status: 404 });
|
|
}
|
|
|
|
const fileBuffer = localStorage.readFile(filePath);
|
|
const contentType = getContentType(filePath);
|
|
|
|
return new NextResponse(new Uint8Array(fileBuffer), {
|
|
headers: {
|
|
'Content-Type': contentType,
|
|
'Content-Disposition': `inline; filename="${path.basename(filePath)}"`,
|
|
},
|
|
});
|
|
} catch (error) {
|
|
console.error('[Local Storage API] Error:', error);
|
|
return NextResponse.json({ error: 'Internal server error' }, { status: 500 });
|
|
}
|
|
}
|
|
|
|
function normalizeStoragePath(value: string): string | null {
|
|
try {
|
|
const decoded = decodeURIComponent(value);
|
|
const normalized = path.posix.normalize(decoded).replace(/^\/+/, '');
|
|
if (!normalized || normalized.startsWith('..') || normalized.includes('/../') || path.isAbsolute(normalized)) {
|
|
return null;
|
|
}
|
|
return normalized;
|
|
} catch {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
function getContentType(filePath: string): string {
|
|
const extension = filePath.split('.').pop()?.toLowerCase();
|
|
|
|
const contentTypeMap: Record<string, string> = {
|
|
'jpg': 'image/jpeg',
|
|
'jpeg': 'image/jpeg',
|
|
'png': 'image/png',
|
|
'webp': 'image/webp',
|
|
'gif': 'image/gif',
|
|
'mp4': 'video/mp4',
|
|
'avi': 'video/x-msvideo',
|
|
'mov': 'video/quicktime',
|
|
'wmv': 'video/x-ms-wmv',
|
|
'pdf': 'application/pdf',
|
|
'txt': 'text/plain',
|
|
'json': 'application/json',
|
|
};
|
|
|
|
return contentTypeMap[extension || ''] || 'application/octet-stream';
|
|
}
|