Initial miaojingAI project with image resolution guard
This commit is contained in:
64
src/app/api/local-storage/[...path]/route.ts
Normal file
64
src/app/api/local-storage/[...path]/route.ts
Normal file
@@ -0,0 +1,64 @@
|
||||
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';
|
||||
}
|
||||
Reference in New Issue
Block a user