import fs from 'fs'; import path from 'path'; import { NextResponse } from 'next/server'; const BACKEND_SERVER_URL = process.env.BACKEND_SERVER_URL || ''; const PUBLIC_FILES_DIR = path.join(process.cwd(), 'public/files'); function getContentType(filePath) { const ext = path.extname(filePath).toLowerCase(); switch (ext) { case '.jpg': case '.jpeg': return 'image/jpeg'; case '.png': return 'image/png'; case '.gif': return 'image/gif'; case '.svg': return 'image/svg+xml'; case '.webp': return 'image/webp'; case '.mp4': return 'video/mp4'; case '.pdf': return 'application/pdf'; default: return 'application/octet-stream'; } } export async function GET(req, { params }) { try { const parts = params.path || []; const fileName = parts.join('/'); if (!fileName) return new NextResponse('Not Found', { status: 404 }); const localPath = path.join(PUBLIC_FILES_DIR, fileName); if (fs.existsSync(localPath)) { const data = fs.readFileSync(localPath); return new NextResponse(data, { status: 200, headers: { 'Content-Type': getContentType(localPath), 'Cache-Control': 'public, max-age=31536000, immutable' } }); } const remoteUrl = `${BACKEND_SERVER_URL}/files/${fileName}`; const res = await fetch(remoteUrl); if (!res.ok) { // 占位图(SVG),避免前端空白 const placeholder = `Image unavailable`; return new NextResponse(placeholder, { status: 200, headers: { 'Content-Type': 'image/svg+xml', 'Cache-Control': 'no-store' } }); } const arrayBuffer = await res.arrayBuffer(); const buffer = Buffer.from(arrayBuffer); // 确保目录存在并写入本地 fs.mkdirSync(path.dirname(localPath), { recursive: true }); fs.writeFileSync(localPath, buffer); return new NextResponse(buffer, { status: 200, headers: { 'Content-Type': getContentType(localPath), 'Cache-Control': 'public, max-age=31536000, immutable' } }); } catch (e) { return new NextResponse('Server Error', { status: 500, headers: { 'Cache-Control': 'no-store' } }); } }