Files
beavergram/frontend/src/lib/api/download.ts
T

62 lines
1.8 KiB
TypeScript

import { accounts } from "$lib/stores/accounts.svelte";
import { auth } from "$lib/stores/auth.svelte";
const BASE = import.meta.env.VITE_API_BASE ?? "/api";
const FILENAME_STAR = /filename\*=UTF-8''([^;]+)/i;
const FILENAME_PLAIN = /filename="?([^";]+)"?/i;
function nameFromHeader(header: string | null, fallback: string): string {
if (!header) {
return fallback;
}
const encoded = FILENAME_STAR.exec(header);
if (encoded) {
return decodeURIComponent(encoded[1]);
}
const plain = FILENAME_PLAIN.exec(header);
return plain ? plain[1] : fallback;
}
function saveBlob(blob: Blob, fileName: string) {
const url = URL.createObjectURL(blob);
const link = document.createElement("a");
link.href = url;
link.download = fileName;
document.body.append(link);
link.click();
link.remove();
setTimeout(() => URL.revokeObjectURL(url), 1000);
}
async function save(path: string, fallback: string): Promise<void> {
const response = await fetch(`${BASE}${path}`, {
headers: auth.token ? { Authorization: `Bearer ${auth.token}` } : {},
});
if (!response.ok) {
throw new Error(`download failed: ${response.status}`);
}
const fileName = nameFromHeader(
response.headers.get("content-disposition"),
fallback
);
saveBlob(await response.blob(), fileName);
}
export function downloadMedia(mediaId: number): Promise<void> {
return save(`/media/${mediaId}?download=true`, `media_${mediaId}`);
}
export function downloadMediaVersion(versionId: number): Promise<void> {
return save(
`/media/version/${versionId}?download=true`,
`media_${versionId}`
);
}
export function downloadStory(peerId: number, storyId: number): Promise<void> {
return save(
`/stories/${peerId}/${storyId}/media?download=true&account_id=${accounts.selectedId}`,
`story_${peerId}_${storyId}`
);
}