给定url,前端下载zip文件

21 阅读1分钟

背景:后端已经将zip文件的URL传过来,前端需要带token下载这个zip文件

下载函数如下


function getFilenameFromHeadersOrUrl(disposition: string | undefined, url: string) {
  let filename = '';
  if (disposition) {
    const m1 = disposition.match(/filename\*\s*=\s*UTF-8''([^;]+)/i);
    const m2 = disposition.match(/filename\s*=\s*"?([^";]+)"?/i);
    filename = decodeURIComponent((m1?.[1] || m2?.[1] || '').trim());
  }
  if (!filename) {
    const parts = url.split('/');
    filename = decodeURIComponent(parts[parts.length - 1] || 'download');
  }
  return filename;
}

async function downloadFile(url: string) {
  const safeUrl = encodeURI(url);
  try {
    downloading.value = true;
    const response = await axios.get(safeUrl, {
      responseType: 'blob',
      headers: {
        Authorization: `Bearer ${localStorage.getItem('userToken')}`,
      },
      onDownloadProgress: (evt) => {
        // total 可能为空(服务器未返回 Content-Length)
        if (typeof evt.total === 'number' && evt.total > 0) {
          downloadPercent.value = Math.min(100, Math.floor((evt.loaded / evt.total) * 100));
        } else {
          downloadPercent.value = null;
        }
      },
    });

    // 1) 尝试从 Content-Disposition 拿文件名
    const disposition = response.headers?.['content-disposition'] as string | undefined;
    const filename = getFilenameFromHeadersOrUrl(disposition, url);
    downloadFilename.value = filename;

    const blob = response.data as Blob;
    const downloadUrl = window.URL.createObjectURL(blob);

    const a = document.createElement('a');
    a.href = downloadUrl;
    a.download = filename;
    document.body.appendChild(a);
    a.click();

    document.body.removeChild(a);
    window.URL.revokeObjectURL(downloadUrl);
    message.success('下载成功');
  } catch (error) {
    console.error('下载失败:', error);
    message.error('下载失败,请重试');
  } finally {
    downloading.value = false;
    downloadPercent.value = null;
    downloadFilename.value = '';
  }
}