File size: 1,797 Bytes
c4ae742 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 | export async function apiFetch<T>(url: string, options?: RequestInit): Promise<T> {
const response = await fetch(url, options);
const payload = await response.json().catch(() => null);
if (!response.ok || !payload || payload.code !== 0) {
throw new Error(payload?.msg || `HTTP ${response.status}`);
}
return payload.data as T;
}
export async function downloadBlob(url: string, fallbackName: string): Promise<void> {
const response = await fetch(url);
if (!response.ok) {
const payload = await response.json().catch(() => null);
throw new Error(payload?.msg || `HTTP ${response.status}`);
}
const blob = await response.blob();
const filename = filenameFromDisposition(response.headers.get("Content-Disposition")) || fallbackName;
const objectURL = URL.createObjectURL(blob);
try {
const link = document.createElement("a");
link.href = objectURL;
link.download = filename;
document.body.appendChild(link);
link.click();
link.remove();
} finally {
URL.revokeObjectURL(objectURL);
}
}
export function filenameFromDisposition(disposition: string | null): string {
if (!disposition) return "";
const utf8 = /filename\*=UTF-8''([^;]+)/i.exec(disposition);
if (utf8) return decodeURIComponent(utf8[1]);
const quoted = /filename="([^"]+)"/i.exec(disposition);
if (quoted) return quoted[1];
return "";
}
export function downloadText(filename: string, content: string, type: string): void {
const blob = new Blob([content], { type });
const objectURL = URL.createObjectURL(blob);
try {
const link = document.createElement("a");
link.href = objectURL;
link.download = filename;
document.body.appendChild(link);
link.click();
link.remove();
} finally {
URL.revokeObjectURL(objectURL);
}
}
|