BillTracker/client/lib/download.ts

27 lines
1.0 KiB
TypeScript
Raw Permalink Normal View History

// Shared blob download: fetches an endpoint and saves the response as a file.
// Works whether or not the response sets Content-Disposition (some exports
// don't), falling back to the given name. Throws on a non-OK response so callers
// can surface the failure with a toast.
export async function downloadFile(endpoint: string, fallbackName: string): Promise<void> {
const res = await fetch(endpoint, { credentials: 'include' });
if (!res.ok) {
let data: { message?: string; error?: string } = {};
try {
data = await res.json();
} catch {
/* ignore */
}
throw new Error(data.message || data.error || `HTTP ${res.status}`);
}
const disposition = res.headers.get('Content-Disposition');
const match = disposition?.match(/filename="?([^"]+)"?/i);
const name = match?.[1] || fallbackName;
const blob = await res.blob();
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = name;
a.click();
URL.revokeObjectURL(url);
}