import fs from 'fs'; export function setCommonNoCacheHeaders(res) { res.setHeader('Cache-Control', 'no-store'); res.setHeader('Accept-Ranges', 'bytes'); } export function headFile(res, { size, mime }) { setCommonNoCacheHeaders(res); res.setHeader('Content-Type', mime); res.setHeader('Content-Length', size); res.status(200).end(); } export function streamFile(req, res, { filePath, mime }) { const stat = fs.statSync(filePath); const size = stat.size; const range = req.headers.range; setCommonNoCacheHeaders(res); if (range) { const match = /bytes=(\d+)-(\d+)?/.exec(range); let start = match?.[1] ? parseInt(match[1], 10) : 0; let end = match?.[2] ? parseInt(match[2], 10) : size - 1; if (Number.isNaN(start)) start = 0; if (Number.isNaN(end)) end = size - 1; start = Math.min(Math.max(0, start), Math.max(0, size - 1)); end = Math.min(Math.max(start, end), Math.max(0, size - 1)); if (start > end || start >= size) { res.setHeader('Content-Range', `bytes */${size}`); return res.status(416).end(); } const chunkSize = end - start + 1; res.writeHead(206, { 'Content-Range': `bytes ${start}-${end}/${size}`, 'Content-Length': chunkSize, 'Content-Type': mime, }); fs.createReadStream(filePath, { start, end }).pipe(res); } else { res.writeHead(200, { 'Content-Length': size, 'Content-Type': mime, }); fs.createReadStream(filePath).pipe(res); } }