JavaScript
Download upload.mjs ↓Node.js 22 or later. No extra packages.
Save it as upload.mjs, then run
node upload.mjs ./manual.pdfSource59 lines
import { open } from "node:fs/promises";
import { basename } from "node:path";
const origin = (process.env.STASHBAY_ORIGIN ?? "https://stashbay.net").replace(/\/$/, "");
const key = process.env.STASHBAY_API_KEY;
const path = process.argv[2];
if (!key || !path) throw new Error("Set STASHBAY_API_KEY and run: node upload.mjs FILE");
async function api(path, body) {
const response = await fetch(`${origin}/api/v1${path}`, {
method: "POST",
headers: { Authorization: `Bearer ${key}`, "Content-Type": "application/json" },
body: JSON.stringify(body),
redirect: "error",
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
return response.json();
}
const file = await open(path, "r");
try {
const { size } = await file.stat();
const plan = await api("/uploads/init", { filename: basename(path), sizeBytes: size });
console.error(`Upload ID: ${plan.fileId}`);
if (!Number.isSafeInteger(plan.partSize) || plan.partSize < 1 || plan.partSize > 64 * 1024 * 1024) {
throw new Error("Unexpected part size");
}
const parts = [];
for (let number = 1; number <= plan.partCount; number++) {
const offset = (number - 1) * plan.partSize;
const bytes = Buffer.alloc(Math.min(plan.partSize, size - offset));
let filled = 0;
while (filled < bytes.length) {
const { bytesRead } = await file.read(bytes, filled, bytes.length - filled, offset + filled);
if (!bytesRead) throw new Error("File changed during upload");
filled += bytesRead;
}
const address = plan.single ? plan.uploadUrl :
(await api("/uploads/parts", { fileId: plan.fileId, from: number, count: 1 })).parts[0].url;
const url = new URL(address, origin);
const headers = {};
if (plan.strategy === "proxy" && url.origin === new URL(origin).origin) {
headers.Authorization = `Bearer ${key}`;
} else if (plan.strategy !== "presigned" || url.protocol !== "https:") {
throw new Error("Unexpected upload URL or strategy");
}
const response = await fetch(url, { method: "PUT", headers, body: bytes, redirect: "error" });
if (!response.ok) throw new Error(`PUT ${response.status}: ${await response.text()}`);
if (!plan.single) {
const etag = plan.strategy === "proxy" ? (await response.json()).etag : response.headers.get("etag");
if (!etag) throw new Error("Missing part ETag");
parts.push({ partNumber: number, etag: etag.replace(/^"|"$/g, "") });
}
}
const result = await api("/uploads/complete", { fileId: plan.fileId, parts });
console.log(result.shareUrl ?? JSON.stringify(result));
} finally {
await file.close();
}