import axios from 'axios' import { ref } from 'vue' export function useDownload() { const isDownloading = ref(false) const downloadFile = async ( url: string, filename?: string, token?: string, headers?: Record, ): Promise => { if (isDownloading.value) return try { isDownloading.value = true // Build headers const requestHeaders: Record = { ...headers } if (token && !requestHeaders.Authorization) { requestHeaders.Authorization = `Bearer ${token}` } // Use direct axios call with headers const response = await axios.get(url, { responseType: 'blob', ...(Object.keys(requestHeaders).length > 0 && { headers: requestHeaders }), }) const blob = new Blob([response.data], { type: response.data.type }) const blobUrl = URL.createObjectURL(blob) // Extract filename from Content-Disposition header or use provided/default let finalFilename = filename const contentDisposition = response.headers['content-disposition'] || response.headers['Content-Disposition'] if (contentDisposition) { try { const utf8Match = contentDisposition.match(/filename\*=UTF-8''([^;]+)/i) const basicMatch = contentDisposition.match(/filename="?([^";]+)"?/i) const rawFilename = utf8Match?.[1] ?? basicMatch?.[1] if (rawFilename) { finalFilename = decodeURIComponent(rawFilename.replace(/\+/g, '%20')) } } catch { // Fallback if parsing fails } } if (!finalFilename) { finalFilename = url.substring(url.lastIndexOf('/') + 1) || 'download' } // Create and trigger download const link = document.createElement('a') link.href = blobUrl link.download = finalFilename document.body.appendChild(link) link.click() // Cleanup setTimeout(() => { document.body.removeChild(link) URL.revokeObjectURL(blobUrl) }, 100) } catch (error) { console.error('Download failed:', error) throw error } finally { isDownloading.value = false } } return { downloadFile, isDownloading, } }