code quality improvements and improved file error handling

This commit is contained in:
2025-09-17 11:39:26 +01:00
parent b98e3ed85d
commit 0b7ab3b0de
20 changed files with 226 additions and 144 deletions

View File

@@ -0,0 +1,64 @@
// CORS (server missing Access-Control-Allow-* headers)??
type BlobFileUpload = {
file: File | null;
opts?: {
timeoutMs?: number;
fieldName?: string;
overrideFileName?: string;
uploadUrl: URL | string;
};
};
export async function sendBlobFileUpload({
file,
opts,
}: BlobFileUpload): Promise<string> {
if (!file) throw new Error("No file supplied");
if (!opts?.uploadUrl) throw new Error("No URL supplied");
if (file?.type !== "text/csv") {
throw new Error("This file is not supported, please upload a CSV file.");
}
const timeoutMs = opts?.timeoutMs ?? 30000;
const fieldName = opts?.fieldName ?? "upload";
const fileName = opts?.overrideFileName ?? file?.name;
const controller = new AbortController();
const timeout = setTimeout(() => controller.abort(), timeoutMs);
try {
const form = new FormData();
form.append(fieldName, file, fileName);
const resp = await fetch(opts?.uploadUrl, {
method: "POST",
body: form,
signal: controller.signal,
redirect: "follow",
});
const bodyText = await resp.text();
if (!resp.ok) {
throw new Error(
`Upload failed (${resp.status} ${resp.statusText}) from ${opts.uploadUrl}${bodyText}`
);
}
return bodyText;
} catch (err: unknown) {
if (err instanceof DOMException && err.name === "AbortError") {
throw new Error(`Timeout uploading to ${opts.uploadUrl}.`);
}
// In browsers, fetch throws TypeError on network-level failures
if (err instanceof TypeError) {
throw new Error(
`HTTP error uploading to ${opts.uploadUrl}: ${err.message}`
);
}
throw new Error("HTTP method POST is not supported by this URL");
} finally {
clearTimeout(timeout);
}
}