type MimeType = | "text/plain" | "text/html" | "text/css" | "text/javascript" | "text/csv" | "application/json" | "application/xml" | "application/pdf" | "application/zip" | "application/octet-stream" | "image/png" | "image/jpeg" | "image/gif" | "image/svg+xml" | "audio/mpeg" | "audio/wav" | "video/mp4" | "video/webm" | (string & {}); type DownloadableContent = | [string, MimeType] | [Blob, MimeType] | [ArrayBuffer, MimeType] | [Uint8Array, MimeType] | [Int8Array, MimeType] | [Uint16Array, MimeType] | [Int16Array, MimeType] | [Uint32Array, MimeType] | [Int32Array, MimeType] | [Float32Array, MimeType] | [Float64Array, MimeType] | [DataView, MimeType] | Blob // Blob already has mimeType | File; // File already has mimeType export const downloadContent = (content: DownloadableContent, filename: string) => { let blob: Blob; if (content instanceof Blob) { blob = content; } else if (content instanceof File) { blob = content; } else if (Array.isArray(content) && content.length === 2) { const [data, mimeType] = content; if (typeof data === "string") { blob = new Blob([data], { type: mimeType }); } else if (data instanceof ArrayBuffer || ArrayBuffer.isView(data)) { blob = new Blob([data as BlobPart], { type: mimeType }); } else if (data instanceof Blob) { blob = new Blob([data], { type: mimeType }); } else { throw new Error(`Unsupported data type for download. Received data of type ${typeof data}.`); } } else { throw new Error( "Invalid content type. Content must be a Blob, File, or [data, mimeType] tuple.", ); } const objectUrl = URL.createObjectURL(blob); try { const link = document.createElement("a"); link.href = objectUrl; link.download = filename; document.body.appendChild(link); link.click(); document.body.removeChild(link); } catch (error) { throw new Error(`Failed to download ${filename}`, { cause: error }); } finally { URL.revokeObjectURL(objectUrl); } };