BillTracker/client/lib/download.ts

21 lines
1003 B
TypeScript

// 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);
}