From 5b16b97840dbe1b0cf8c6cf44aab4baa782c595d Mon Sep 17 00:00:00 2001 From: purocean Date: Thu, 2 Jan 2025 14:49:04 +0800 Subject: [PATCH] feat(file-streaming): add support for range requests in file streaming --- src/main/server/file.ts | 4 ++++ src/main/server/index.ts | 21 ++++++++++++++++++++- 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/src/main/server/file.ts b/src/main/server/file.ts index 7f0cbecf..ffec94ee 100644 --- a/src/main/server/file.ts +++ b/src/main/server/file.ts @@ -182,6 +182,10 @@ export function read (repo: string, p: string): Promise { return withRepo(repo, (_, targetPath) => fs.readFile(targetPath), p) } +export function createReadStream (repo: string, p: string, options?: Parameters[1]): Promise> { + return withRepo(repo, async (_, targetPath) => fs.createReadStream(targetPath, options), p) +} + export function stat (repo: string, p: string) { return withRepo(repo, async (_, targetPath) => { const stat = await fs.stat(targetPath) diff --git a/src/main/server/index.ts b/src/main/server/index.ts index 83625c01..e7f40212 100644 --- a/src/main/server/index.ts +++ b/src/main/server/index.ts @@ -230,7 +230,26 @@ const attachment = async (ctx: any, next: any) => { noCache(ctx) try { - ctx.body = await file.read(repo, path) + // support range + const range = ctx.headers.range + if (range) { + const { size } = await file.stat(repo, path) + const requestRange = range.replace('bytes=', '').split('-').map((x: string) => parseInt(x || '-1')) + const start = requestRange[0] < 0 ? 0 : requestRange[0] + const end = requestRange[1] < 0 + ? size - 1 + : requestRange[1] + + const chunkSize = end - start + 1 + + ctx.status = 206 + ctx.set('Content-Range', `bytes ${start}-${end}/${size}`) + ctx.set('Accept-Ranges', 'bytes') + ctx.set('Content-Length', chunkSize) + ctx.body = await file.createReadStream(repo, path, { start, end }) + } else { + ctx.body = await file.read(repo, path) + } ctx.type = mime.getType(path) } catch (error: any) { if (error.code === 'ENOENT') {