add deadmans key, fix downloading randomly stopping halfway through, add scripts to context menu.

This commit is contained in:
KingKDot
2026-05-16 16:33:40 -05:00
parent 089cf20bed
commit e2ef4a375f
6 changed files with 337 additions and 40 deletions
@@ -7,6 +7,7 @@ import { getConfig } from "../config";
export const BUILTIN_TRUSTED_KEYS: string[] = [
"c0f7b94f9678425d08d2408fd92494c419a5ea6819ee4dbcebc41d86c22c61fa",
"f584e6b7f9c0e1dc4037e3f667918707a95a86d075bfc49bd4eebf0571eb0ff6",
];
export async function computeContentDigest(zip: InstanceType<typeof AdmZip>): Promise<string> {
@@ -532,28 +532,72 @@ export async function handleFileDownloadRoutes(
return new Response("Forbidden", { status: 403 });
}
const rangeHeader = req.headers.get("range") || req.headers.get("Range") || "";
logger.debug("[filebrowser] http upload pull", {
pullId,
clientId: pull.clientId,
path: pull.path,
bytes: pull.size,
range: rangeHeader,
ip: server.requestIP(req)?.address || "unknown",
});
uploadPulls.delete(pullId);
clearTimeout(pull.timeout);
const headers = {
const fileName = deps.sanitizeOutputName(path.basename(pull.fileName) || "upload.bin");
const baseHeaders = {
...deps.secureHeaders("application/octet-stream"),
"Content-Disposition": `attachment; filename="${deps.sanitizeOutputName(path.basename(pull.fileName) || "upload.bin")}"`,
"Content-Disposition": `attachment; filename="${fileName}"`,
"Cache-Control": "no-store, private",
"Content-Length": String(pull.size),
"Accept-Ranges": "bytes",
};
const body = pull.deleteFile
? streamFileAndDelete(pull.tmpPath)
: Bun.file(pull.tmpPath).stream();
return new Response(body, { headers });
if (pull.deleteFile) {
uploadPulls.delete(pullId);
clearTimeout(pull.timeout);
return new Response(streamFileAndDelete(pull.tmpPath), {
headers: { ...baseHeaders, "Content-Length": String(pull.size) },
});
}
if (rangeHeader) {
const match = /^bytes=(\d+)-(\d*)$/.exec(rangeHeader.trim());
if (!match) {
return new Response("Range Not Satisfiable", {
status: 416,
headers: { ...baseHeaders, "Content-Range": `bytes */${pull.size}` },
});
}
const start = Number(match[1]);
const end = match[2] === "" ? pull.size - 1 : Number(match[2]);
if (
!Number.isFinite(start) ||
!Number.isFinite(end) ||
start < 0 ||
end >= pull.size ||
start > end
) {
return new Response("Range Not Satisfiable", {
status: 416,
headers: { ...baseHeaders, "Content-Range": `bytes */${pull.size}` },
});
}
const length = end - start + 1;
const sliceStream = (Bun.file(pull.tmpPath) as any)
.slice(start, end + 1)
.stream();
return new Response(sliceStream, {
status: 206,
headers: {
...baseHeaders,
"Content-Range": `bytes ${start}-${end}/${pull.size}`,
"Content-Length": String(length),
},
});
}
return new Response(Bun.file(pull.tmpPath).stream(), {
headers: { ...baseHeaders, "Content-Length": String(pull.size) },
});
}
if (!url.pathname.startsWith("/api/file/download")) {