export async function fetchAuthenticatedMediaBlob(accessUrl: string, token: string, mimeType?: string) { const response = await fetch(accessUrl, { headers: { Authorization: `Bearer ${token}` } }); if (!response.ok) { throw new Error('Не удалось загрузить файл'); } const raw = await response.blob(); if (mimeType && (!raw.type || raw.type === 'application/octet-stream')) { return new Blob([await raw.arrayBuffer()], { type: mimeType }); } return raw; } export function createBlobObjectUrl(blob: Blob) { return URL.createObjectURL(blob); } export function revokeBlobObjectUrl(url?: string) { if (url?.startsWith('blob:')) { URL.revokeObjectURL(url); } } export function triggerBlobDownload(blob: Blob, fileName: string) { const objectUrl = URL.createObjectURL(blob); const anchor = document.createElement('a'); anchor.href = objectUrl; anchor.download = fileName; anchor.rel = 'noopener'; document.body.appendChild(anchor); anchor.click(); anchor.remove(); URL.revokeObjectURL(objectUrl); } export function mediaExpiresAtMs(expiresAt?: string) { if (!expiresAt) return Date.now() + 14 * 60_000; const parsed = Date.parse(expiresAt); return Number.isFinite(parsed) ? parsed : Date.now() + 14 * 60_000; } export function shouldRefreshMedia(expiresAtMs: number, bufferMs = 60_000) { return expiresAtMs - Date.now() <= bufferMs; }