From d9216fe8ce423b01be2479a4f4359484a4d610f3 Mon Sep 17 00:00:00 2001 From: reidlab Date: Tue, 24 Mar 2026 15:09:47 -0700 Subject: [PATCH] don't flush album data all at once --- src/web/endpoints/back/download.ts | 4 ++- src/web/endpoints/back/downloadAlbum.ts | 35 ++++++++----------------- 2 files changed, 14 insertions(+), 25 deletions(-) diff --git a/src/web/endpoints/back/download.ts b/src/web/endpoints/back/download.ts index c150cf0..0c17636 100644 --- a/src/web/endpoints/back/download.ts +++ b/src/web/endpoints/back/download.ts @@ -60,9 +60,11 @@ router.get(path, async (req, res, next) => { // TODO: stream to user const filePath = await downloadSongFile(streamInfo.streamUrl, decryptionKey, codecType.codecType, trackMetadata); const fileExt = "." + filePath.split(".").at(-1) as string; // safe cast, filePath is always a valid path - const fileName = formatSongForFs(trackAttributes) + fileExt; + const fileName = formatSongForFs(trackAttributes) + fileExt; res.attachment(fileName); + res.flushHeaders(); + res.sendFile(filePath, { root: "." }); } catch (err) { next(err); diff --git a/src/web/endpoints/back/downloadAlbum.ts b/src/web/endpoints/back/downloadAlbum.ts index 43ec618..a952476 100644 --- a/src/web/endpoints/back/downloadAlbum.ts +++ b/src/web/endpoints/back/downloadAlbum.ts @@ -32,22 +32,24 @@ paths[path] = { } }; -interface AlbumEntry { - path: string; - name: string; -} - // TODO: include album art? router.get(path, async (req, res, next) => { try { const { id, codec } = (await validate(req, schema)).query; - const files: AlbumEntry[] = []; - const albumMetadata = await appleMusicApi.getAlbum(id); const albumAttributes = albumMetadata.data[0].attributes; const tracks = albumMetadata.data[0].relationships.tracks.data; + const fileName = formatAlbumForFs(albumAttributes) + ".zip"; + res.attachment(fileName); + res.flushHeaders(); + + const zipArchiver = archiver("zip"); + zipArchiver.pipe(res); + zipArchiver.on("error", (err) => { throw err; }); + zipArchiver.on("warning", (err) => { throw err; }); + for (const track of tracks) { const trackId = track.attributes.playParams?.id; if (trackId === undefined) { throw new Error("track id gone, this may indicate your song isn't accessable w/ your subscription!"); } @@ -75,28 +77,13 @@ router.get(path, async (req, res, next) => { const fileExt = "." + filePath.split(".").at(-1) as string; // safe cast, filePath is always a valid path const fileName = formatSongForFs(trackAttributes) + fileExt; - files.push({ - path: filePath, - name: fileName - }); - } - - const fileName = formatAlbumForFs(albumAttributes) + ".zip"; - const zipArchiver = archiver("zip"); - - zipArchiver.on("error", (err) => { throw err; }); - zipArchiver.pipe(res); - - for (const file of files) { - zipArchiver.file(file.path, { name: file.name }); + zipArchiver.file(filePath, { name: fileName }); } const albumCover = await downloadAlbumCover(albumAttributes); const albumCoverExt = albumCover.slice(albumCover.lastIndexOf(".") + 1); - zipArchiver.file(await downloadAlbumCover(albumAttributes), { name: `cover.${albumCoverExt}` }); + zipArchiver.file(albumCover, { name: `cover.${albumCoverExt}` }); zipArchiver.finalize(); - - res.attachment(fileName); } catch (err) { next(err); }