前端文件下载全攻略:从单文件到批量下载,哪种方法最优?

小张是一名刚入职的前端开发工程师,某天,他的领导给他布置了一个看似简单的任务:

让用户能够通过文件链接下载多个文件

小张信心满满,觉得这不过是个小问题。然而,当他真正动手时,才发现这个需求并不简单。不同的下载方式各有优缺点,甚至有些方法会带来意想不到的问题,他决定一一尝试,探索最优解。

方案一:window.open------简单粗暴,但会打开新标签页

小张首先想到的是 window.open(url),它可以让浏览器直接打开下载链接。

js 复制代码
window.open('https://example.com/file.pdf');

优点

  • 代码简单,直接调用即可。
  • 适用于单个文件的下载。

缺点

  • 每次下载都会打开一个新的浏览器标签页,影响用户体验。
  • 部分浏览器可能会拦截 window.open,导致下载失败。

方案二:window.location.href 简单有效,但不能同时下载多个文件

小张发现,window.location.href 也可以实现下载,且不会打开新标签页。

js 复制代码
window.location.href = 'https://example.com/file.pdf';

优点

  • 适用于单文件下载。
  • 不会像 window.open 那样打开新页面。

缺点

  • 无法循环下载多个文件 。如果连续多次赋值 window.location.href,后一个请求会覆盖前一个,导致只能下载最后一个文件。

方案三:iframe 支持多文件下载,但无法监听完成状态

为了让多个文件能够顺利下载,小张尝试用 iframe

js 复制代码
function downloadFile(url) {
  const iframe = document.createElement('iframe');
  iframe.style.display = 'none';
  iframe.src = url;
  document.body.appendChild(iframe);
  setTimeout(() => {
    document.body.removeChild(iframe);
  }, 5000); // 延迟移除 iframe,防止影响下载
}

优点

  • 适用于多文件下载。

缺点

  • iframe 无法监听文件下载是否完成。
  • 需要在合适的时机移除 iframe,否则可能会影响页面性能。

方案四:fetch + blob------最优雅的下载方式

小张最终发现,fetch 可以获取文件数据,再通过 Blob 处理并使用 a 标签下载。

js 复制代码
async function downloadFile(url, fileName) {
  const response = await fetch(url);
  if (!response.ok) throw new Error('Download failed');
  const blob = await response.blob();
  const blobUrl = URL.createObjectURL(blob);
  const a = document.createElement('a');
  a.href = blobUrl;
  a.download = fileName;
  document.body.appendChild(a);
  a.click();
  document.body.removeChild(a);
  URL.revokeObjectURL(blobUrl);
}

function download(fileList){
   for(const file of fileList) {
     await downloadFile(file.url,file.name)
   }
}

优点

  • 不会打开新标签页。
  • 可以同时下载多个文件。
  • 适用于现代浏览器,兼容性较好。

缺点

  • 需要处理异步 fetch 请求。
  • 服务器必须支持跨域资源共享(CORS),否则 fetch 请求会失败。
  • 多次文件下载会导致多个浏览器下载图标 :每次调用 a.click() 时,浏览器都会显示一个下载图标,影响用户体验。

方案五:jsZip 打包多个文件为 ZIP 下载------避免多次下载图标

为了进一步优化方案四,避免浏览器每次下载时显示多个下载图标,小张决定使用 jsZip 插件将多个文件打包成一个 ZIP 文件下载。

js 复制代码
import JSZip from 'jszip';

async function downloadFilesAsZip(files) {
  const zip = new JSZip();
  // 循环遍历多个文件,获取每个文件的数据
  for (const file of files) {
    const response = await fetch(file.url);
    if (!response.ok) throw new Error(`Failed to fetch ${file.name}`);
    const blob = await response.blob();
    zip.file(file.name, blob); // 将文件添加到 ZIP 包中
  }

  // 生成 ZIP 文件并触发下载
  zip.generateAsync({ type: "blob" })
    .then(function(content) {
      const a = document.createElement('a');
      const blobUrl = URL.createObjectURL(content);
      a.href = blobUrl;
      // 给压缩包设置下载文件名
      a.download = 'files.zip';
      document.body.appendChild(a);
      a.click();
      document.body.removeChild(a);
      // 释放 URL 对象
      URL.revokeObjectURL(blobUrl);
    });
}

优点

  • 提升用户体验:用户下载一个压缩包后,只需解压就可以获取所有文件,避免了多次点击和等待的麻烦。
  • 适用于多文件下载:非常适合需要批量下载的场景。

缺点

  • 浏览器对大文件的支持:如果要下载的文件非常大,或者文件总大小很大,可能会导致内存消耗过高,甚至在浏览器中崩溃。
  • 下载速度受限于压缩处理:打包文件为 ZIP 需要时间,尤其是文件较多时,会稍微影响压缩的速度,只适用于文件不是很大且数量不是很多的时候

结语:小张的最终选择

经过一番探索,小张最终选择了 jsZip 打包文件的方案,因为它不仅解决了多个文件下载时图标显示的问题,还提高了用户体验,让下载更加流畅,没有哪个方案比另外一个方案好,只有最适合的方案,根据实际的场景能满足需求最优解就是最好的。

相关推荐
雪芽蓝域zzs6 分钟前
第四十八节:驾驶舱大屏进阶:数字滚动动画 + 渐变边框美化
前端·javascript·vue.js
ly768911 分钟前
Spring Boot 3.2 虚拟线程在 Web 层与 JDBC 池的实践边界
前端·spring boot·后端·tomcat·jdbc·虚拟线程
Bingo_BIG14 分钟前
LOV列表的查询
前端·javascript·lov
小静AI工程实验室25 分钟前
JS 逆向接口 ID 变了?Python 与 Node.js 复现 JSON 大整数精度丢失
javascript·python·node.js
Setsuna_F_Seiei7 小时前
前端转型 Agent 开发 04 之 MCP 与 Skill(赋予 Agent 更广工作能力)
前端·agent
刘发财9 小时前
前端2秒生成500页矢量PDF,rust真的强到没朋友
前端·javascript·rust
郑州光合科技余经理9 小时前
国际版外卖系统:税率字段怎么和订单主流程解耦
android·java·开发语言·前端·后端·php·ai编程
梦想平凡10 小时前
百游棋牌源代码开发搭建教程(十):隔离部署、备份恢复与双端验收
java·前端·javascript·数据库·源代码管理
yume_sibai11 小时前
06-Rust Web 开发实战(Axum 框架 + 数据库 + JWT 认证 + 中间件 + 部署)
前端·数据库·rust
计算机魔术师12 小时前
特朗普上台打给黄仁勋:AI末日论是骗局,我们绝不让它发生
前端