-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbrowserDownload.ts
More file actions
43 lines (41 loc) · 1.31 KB
/
Copy pathbrowserDownload.ts
File metadata and controls
43 lines (41 loc) · 1.31 KB
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
/**
* Minimal browser download helpers — fetch blob + `<a download>`, with
* `window.open` fallback when CORS or opaque responses block blob access.
*
* Gene: `sdk.media.gen1` · consumer surfaces (lightbox menu, storage, chat).
*/
export function sanitizeDownloadFilename(name: string): string {
const s = name.replace(/[/\\?%*:|"<>#]/g, '_').trim() || 'download';
return s.length > 120 ? s.slice(0, 120) : s;
}
/**
* Attempt same-origin / CORS-enabled download; otherwise opens URL in a new tab.
*/
export async function downloadUrlAsFile(
url: string,
filename: string,
init?: RequestInit
): Promise<void> {
if (typeof window === 'undefined' || typeof document === 'undefined') return;
const safe = sanitizeDownloadFilename(filename);
try {
const res = await fetch(url, {
mode: 'cors',
credentials: 'include',
...init,
});
if (!res.ok) throw new Error(`http_${res.status}`);
const blob = await res.blob();
const objectUrl = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = objectUrl;
a.download = safe;
a.rel = 'noopener';
document.body.appendChild(a);
a.click();
a.remove();
window.setTimeout(() => URL.revokeObjectURL(objectUrl), 60_000);
} catch {
window.open(url, '_blank', 'noopener,noreferrer');
}
}