// app/api/download/route.ts import { NextResponse } from 'next/server'; import path from 'path'; import fs from 'fs'; import { RESOURCE_PATH } from '@/lib/constants'; export async function GET(request: Request) { const { searchParams } = new URL(request.url); const project = searchParams.get('project'); const version = searchParams.get('version'); const filename = searchParams.get('filename'); if (!project || !version || !filename) { return NextResponse.json( { error: 'Project, version, and filename parameters are required' }, { status: 400 } ); } // 安全检查:确保 filename 不包含路径遍历字符 if (filename.includes('..') || filename.includes('/') || filename.includes('\\')) { return NextResponse.json( { error: 'Invalid filename' }, { status: 400 } ); } const filePath = path.join(RESOURCE_PATH, project, version, 'apks', filename); try { // 检查文件是否存在 if (!fs.existsSync(filePath)) { return NextResponse.json( { error: 'File not found' }, { status: 404 } ); } // 读取文件并流式返回 const file = fs.readFileSync(filePath); return new NextResponse(file, { headers: { 'Content-Type': 'application/vnd.android.package-archive', 'Content-Disposition': `attachment; filename="${filename}"`, 'Content-Length': file.length.toString(), }, }); } catch (error) { return NextResponse.json( { error: 'Failed to download file' }, { status: 500 } ); } }