From a3641d100ea6e9817821facd995f54fb63f7f86d Mon Sep 17 00:00:00 2001 From: Michael Freno Date: Sun, 6 Sep 2026 18:46:42 -0400 Subject: [PATCH] perf(download): stream response body straight to file Bun.file().writer() per chunk replaces the in-memory chunk array + final concat copy: no more whole-episode buffering. --- src/utils/episode-downloader.ts | 24 ++++++++---------------- 1 file changed, 8 insertions(+), 16 deletions(-) diff --git a/src/utils/episode-downloader.ts b/src/utils/episode-downloader.ts index 055a04f..88d07f0 100644 --- a/src/utils/episode-downloader.ts +++ b/src/utils/episode-downloader.ts @@ -124,17 +124,17 @@ export async function downloadEpisode( } } - const reader = body.getReader() - const chunks: Uint8Array[] = [] + const fileWriter = Bun.file(filePath).writer() let bytesDownloaded = 0 let lastProgressTime = Date.now() let lastProgressBytes = 0 + const reader = body.getReader() while (true) { const { done, value } = await reader.read() if (done) break - chunks.push(value) + fileWriter.write(value) bytesDownloaded += value.length // Report progress roughly every 250ms @@ -152,22 +152,14 @@ export async function downloadEpisode( } } - // Concatenate chunks and write to file - const totalSize = bytesDownloaded - const buffer = new Uint8Array(totalSize) - let offset = 0 - for (const chunk of chunks) { - buffer.set(chunk, offset) - offset += chunk.length - } - - await Bun.write(filePath, buffer) + // Finalize the streamed file + await fileWriter.end() // Final progress report if (onProgress) { onProgress({ - bytesDownloaded: totalSize, - totalBytes: contentLength || totalSize, + bytesDownloaded, + totalBytes: contentLength || bytesDownloaded, percent: 100, speed: 0, }) @@ -176,7 +168,7 @@ export async function downloadEpisode( return { success: true, filePath, - fileSize: totalSize, + fileSize: bytesDownloaded, } } catch (err: unknown) { if (err instanceof DOMException && err.name === "AbortError") {