diff --git a/dripzone-app/src/app/api/download-apk/route.ts b/dripzone-app/src/app/api/download-apk/route.ts index ca8acd7..9b1e2ab 100644 --- a/dripzone-app/src/app/api/download-apk/route.ts +++ b/dripzone-app/src/app/api/download-apk/route.ts @@ -7,26 +7,55 @@ export const dynamic = 'force-dynamic'; export async function GET() { const possiblePaths = [ path.join(process.cwd(), 'public', 'DripZone.apk'), + path.join(process.cwd(), '..', 'public', 'DripZone.apk'), '/app/public/DripZone.apk', - '/home/carlos/apps/dripzone-app/public/DripZone.apk', + path.resolve('public/DripZone.apk'), path.join(process.cwd(), 'DripZone.apk'), ]; - const apkPath = possiblePaths.find((p) => fs.existsSync(p)); - if (!apkPath) { - return new NextResponse('APK no disponible en este momento', { status: 404 }); + let apkPath: string | undefined; + for (const p of possiblePaths) { + try { + if (fs.existsSync(p)) { + apkPath = p; + break; + } + } catch {} } - const stat = fs.statSync(apkPath); - const fileBuffer = fs.readFileSync(apkPath); + if (!apkPath) { + return new NextResponse( + JSON.stringify({ error: 'APK no disponible', searched: possiblePaths, cwd: process.cwd() }), + { status: 404, headers: { 'Content-Type': 'application/json' } } + ); + } - return new NextResponse(fileBuffer, { - status: 200, - headers: { - 'Content-Type': 'application/vnd.android.package-archive', - 'Content-Length': stat.size.toString(), - 'Content-Disposition': 'attachment; filename="DripZone.apk"', - 'Cache-Control': 'public, max-age=3600, must-revalidate', - }, - }); + try { + const stat = fs.statSync(apkPath); + const nodeStream = fs.createReadStream(apkPath); + + // Convert node stream to web ReadableStream for chunked delivery + const webStream = new ReadableStream({ + start(controller) { + nodeStream.on('data', (chunk) => controller.enqueue(chunk)); + nodeStream.on('end', () => controller.close()); + nodeStream.on('error', (err) => controller.error(err)); + }, + cancel() { + nodeStream.destroy(); + }, + }); + + return new Response(webStream, { + status: 200, + headers: { + 'Content-Type': 'application/vnd.android.package-archive', + 'Content-Length': stat.size.toString(), + 'Content-Disposition': 'attachment; filename="DripZone.apk"', + 'Cache-Control': 'public, max-age=3600, must-revalidate', + }, + }); + } catch (err: any) { + return new NextResponse(`Error reading APK: ${err?.message || err}`, { status: 500 }); + } }