详解JS实现单个或多个文件批量下载的方法

这篇具有很好参考价值的文章主要介绍了详解JS实现单个或多个文件批量下载的方法。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

0.JS简介

前言

单个文件Download

方案一:location.href or window.open

方案二:通过a标签的download属性

方案三:API请求

多个文件批量Download

方案一:按单个文件download方式,循环依次下载

方案二:前端打包成zip download

方案三:后端压缩成zip,然后以文件流url形式,前端调用download

总结


0.JS简介

JavaScript是一种基于原型的语言,它意味着它不使用类来定义对象,而是使用原型来定义对象和它们的属性和方法。这种原型继承模式是JavaScript的一个独特特征,使其与其他基于类的语言(如Java和C++)有所不同。

JavaScript在Web开发中扮演着非常重要的角色。在Web应用程序中,它可以用来验证表单、处理数据、响应用户交互等。JavaScript可以与HTML和CSS结合使用,创建交互式的、动态的Web页面。它可以与各种Web框架(如React、Angular和Vue.js)一起使用,以便更轻松地开发大规模的Web应用程序。

除了Web开发之外,JavaScript还可以用于服务器端开发。使用Node.js平台,JavaScript可以用于构建高度可伸缩的Web应用程序和API。Node.js是一个基于事件驱动、非阻塞I/O的平台,它使JavaScript可以在服务器端运行。Node.js包含了许多内置的模块,可以轻松地处理文件、网络、加密和HTTP请求等任务。

JavaScript还可以用于移动应用程序开发。与桌面应用程序不同,移动应用程序需要一种跨平台的语言来开发应用程序。JavaScript可以用于开发基于React Native的移动应用程序,这是一个用于构建原生移动应用程序的开源框架。使用React Native,开发人员可以使用JavaScript开发应用程序,并在iOS和Android上运行相同的代码。

JavaScript的语法相对简单,学习起来比较容易。它有许多内置函数和方法,可以用于处理字符串、数组、对象等常见的数据类型。JavaScript也支持闭包、高阶函数和函数式编程等概念,这些概念使代码更加灵活和可重用。

前言

在前端Web开发中,下载文件是一个很常见的需求,也有一些比较特殊的Case,比如下载文件请求是一个POST、url不是同源的、批量下载文件等。本文就介绍下几种download解决方案,以及特殊Case的最佳方案选择。

单个文件Download

方案一:location.href or window.open

<a href={url} target="_blank">download</a>
window.location.href = url; // 当前tab
window.open(url); // 新tab

缺点:

1.只支持get请求,不支持post请求。

2.浏览器会根据headercontent-type来判断是下载文件还是预览文件。

比如 txt png 等格式文件,会在当前tab或新tab中预览,而不是下载下来。

3.由于只支持get,会有url参数过长问题。

4.不能加request header,无法做权限验证等逻辑。

5.不支持自定义file name。

方案二:通过a标签的download属性

通过HTML a标签的原生属性,使用浏览器下载。

<a> - HTML(超文本标记语言) | MDN

<a href={url} download={fileName}>download</a>
function downloadFile(url, fileName) {
    const a = document.createElement('a');
    a.style.display = 'none';
    a.href = url;
    a.download = fileName;
    document.body.appendChild(a);
    a.click();
    document.body.removeChild(a);
}

优点:

  • 都是走的浏览器下载文件逻辑,不会预览文件。
  • 当前tab打开方式下载。
  • 支持设置file name。

缺点:

  • 只支持get请求,不支持post请求。
  • 不能加request header,无法做权限验证等逻辑。
  • 不支持跨域地址。

方案三:API请求

API发送请求的方式,获取文件blog对象,然后通过URL.createObjectURL方法获取download url,然后用方案二的<a download />方式下载。

// 封装一个fetch download方法
async function fetchDownload(fetchUrl, method = "POST", body = null) {
    const response = await window.fetch(fetchUrl, {
        method,
        body: body ? JSON.stringify(body) : null,
        headers: {
            "Accept": "application/json",
            "Content-Type": "application/json",
            "X-Requested-With": "XMLHttpRequest",
        },
    });
    const fileName = getFileName(response);
    const blob = await response.blob();
    const url = URL.createObjectURL(blob);
    return { blob, url, fileName }; // 返回blob、download url、fileName
}
// 根据response header获取文件名
function getFileName(response) {
    const disposition = response.headers.get('Content-Disposition');

    // 本例格式是:"attachment; filename="img.jpg""
    let fileName = disposition.split('filename=')[1].replaceAll('"', '');

    // 可以根据自己的格式来截取文件名
    // 参考https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/Content-Disposition
    // let fileName = '';
    // if (disposition && disposition.indexOf('attachment') !== -1) {
    //     const matches = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/.exec(disposition);
    //     fileName = matches?.[1]?.replace(/['"]/g, '');
    // }
    fileName = decodeURIComponent(fileName);
    return fileName;
}
// 页面里调用
// get
fetchDownload('/api/get/file?name=img.jpg', 'GET').then(({ blob, url, fileName }) => {
    downloadFile(url, fileName); // 调用方案二的download方法
});
// post
fetchDownload('/api/post/file', 'POST', { name: 'img.jpg' }).then(({ blob, url, fileName }) => {
    downloadFile(url, fileName);
});

URL.createObjectURL 生成的url如果过多会有效率问题,可以在合适的时机(download后)释放掉。

if (window.URL) {
    window.URL.revokeObjectURL(url);
} else {
    window.webkitURL.revokeObjectURL(url);
}

优点:

  • 因为最后用的是方案二,所以满足方案二的优点。
  • 支持post请求、支持跨域(fetch本身支持)。
  • 可以加request header

缺点:

  • 低版本浏览器不支持,可以通过'download' in document.createElement('a')判断是否支持。
  • 浏览器兼容可能有问题,比如Safari、IOS Safari。

多个文件批量Download

有些需求是,点一个按钮需要把多个文件同时download下来,有以下几个方案可以实现。

方案一:按单个文件download方式,循环依次下载

downloadFile("/files/file1.txt", "file1.txt");
downloadFile("/files/word1.docx", "word1.docx");
downloadFile("/files/img1.jpg", "img1.jpg");

利用上面的方案二的<a download />方式下载,会触发浏览器是Download multiple files提示,如果选了Allow则会正常下载。

尝试每个download之间加延迟,依然会弹提示。这个应该是浏览器机制问题了,没办法避免了。

方案二:前端打包成zip download

前端可以通过一个第三方库 jszip,可以把多个文件以blob、base64或纯文本等形式,按自定义的文件结构,压缩成一个zip文件,然后通过浏览器download下来。

// 先封装一个方法,请求返回文件blob
async function fetchBlob(fetchUrl, method = "POST", body = null) {
    const response = await window.fetch(fetchUrl, {
        method,
        body: body ? JSON.stringify(body) : null,
        headers: {
            "Accept": "application/json",
            "Content-Type": "application/json",
            "X-Requested-With": "XMLHttpRequest",
        },
    });
    const blob = await response.blob();
    return blob;
}

const zip = new JSZip();
zip.file("Hello.txt", "Hello World\n"); // 支持纯文本等

zip.file("img1.jpg", fetchBlob('/api/get/file?name=img.jpg', 'GET')); // 支持Promise类型,需要返回数据类型是 String, Blob, ArrayBuffer, etc
zip.file("img2.jpg", fetchBlob('/api/post/file', 'POST', { name: 'img.jpg' })); // 同样支持post请求,只要返回类型正确就行

const folder1 = zip.folder("folder01"); // 创建folder
folder1.file("img3.jpg", fetchBlob('/api/get/file?name=img.jpg', 'GET')); // folder里创建文件

zip.generateAsync({ type: "blob" }).then(blob => {
    const url = window.URL.createObjectURL(blob);
    downloadFile(url, "test.zip");
});

jszip还支持一些别的类型文件压缩,比如纯文本、base64、binary等等,详见:

由于走的是纯前端压缩,所以会有延迟问题,走到最后download时才会调起浏览器下载,所以页面可能需要一个效果来更新压缩进度。zip.generateAsync方法就支持第二个参数,支持进度更新:

zip.generateAsync({ type: "blob" }, metadata => {
    const progress = metadata.percent.toFixed(2); // 保留2位小数
    console.log(metadata.currentFile, "progress: " + progress + " %");
}).then(blob => ... );

方案三:后端压缩成zip,然后以文件流url形式,前端调用download

后台加个api,然后把需要download的文件在后台压缩成zip,然后把文件流输出出来。然后就和单个文件download一样了。

因为后台会先压缩,会有延迟才会把blob返回前台,而且需要传多个文件信息,一般是post请求,所以建议使用单个文件下载的方案三通过API请求实现,在请求前后加上提示语或loading效果。

总结

本文介绍了前端单个文件的下载方案,以及批量多个文件下载的解决方案。最后整理下方案建议:

单个文件下载:

  • 如果url是同源的,并且是一个服务器上的静态文件路径、或者是一个get请求,推荐方案二即 <a download />方式下载。
  • 反之,方案三即API请求方式。

批量文件下载:文章来源地址https://www.toymoban.com/news/detail-427913.html

  • 如果有zip压缩需求,选方案二或方案三;
  • 如果可以接受弹Download multiple files提示,用方案一;反之方案二或方案三;

到了这里,关于详解JS实现单个或多个文件批量下载的方法的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 使用git下载github/gitee仓库部分或单个文件的方法

    有些时候在github或者gitee仓库中我们只需要下载整个项目中的我门需要的那一部分文件夹或文件就行了,不需要下载所有的项目。这样可以节省很多流量和时间 1.建立一个新的 git 本地仓库 这里我在 D:test 中初始化 命令: 2.在本地仓库里面启用sparse-checkout 命令: 3.设定你要

    2024年04月14日
    浏览(92)
  • vue前端开发中,通过vue.config.js配置和nginx配置,实现多个入口文件的实现方法

    由于vue为单页面项目,通过控制组件局部渲染,main.js是整个项目唯一的入口,整个项目都在一个index.html外壳中。 若项目过大,会造成单页面负载过重;同时,多页面利于模块独立部署。 如果项目中不同的页面需要不同的main.js和App.vue这样就需要配置多个入口了。 要单独将页

    2024年01月22日
    浏览(87)
  • Docker宿主机复制(单个文件夹/多个文件/单个文件)到容器

    我的JPEGImages里面包含了多张图片,下面的指令将宿主机JPEGImages目录下的所有文件和子目录复制到7a7608e0bf84容器的/home/PaddleSeg/input/目录下 使用多行docker cp指令 docker cp 容器ID或名称:容器源路径 宿主机目标路径 docker cp 宿主机目标路径 容器ID或名称:容器源路径

    2024年02月08日
    浏览(51)
  • Git提交单个或者多个文件

    Git提交指定文件步骤 1.git status //查看修改的所有内容(或者git status -s) 2.git add ’ ’,例如:(git add components/pages/holders/xxx.vue) //’ \\\'引号中间放上文件名,执行上一步后,会显示文件名跟目录 //多个文件用空格分开 3.git stash -u -k //忽略其他文件,很重要的一步!!!! 4.gi

    2024年02月01日
    浏览(47)
  • 一次理清前端文件上传操作(单个,多个,大文件切片)

    相信大家在工作中也会遇到前端文件上传的需求,虽然已经在项目中使用FormData和elementUI中upload组件都实现过类似上传效果,但自己对这块一直一知半解,因此做一个笔记梳理一下前端方面的文件上传操作,以供日常参考。 总体来说常用的两种方式:二进制传输和base64格式直

    2024年02月03日
    浏览(51)
  • uniApp、微信小程序上传单个文件及多个文件

    使用官方api - uni.uploadFile 这是单个文件上传写法 这是上传多个文件写法 由于没有多个上传文件的方法,目前只能通过遍历的方式来进行多文件上传

    2024年04月16日
    浏览(47)
  • Windows运行单个.bat文件或运行多个.bat文件

    首先创建一个.bat文件,例如 1.bat  ,进入文件编辑,输入你想做的指令,例如: 进入Anaconda虚拟环境,然后运行代码 CALL E:Anaconda3Scriptsactivate.bat E:Anaconda3 CALL conda activate you_name E: cd tensorrt python main.py 将以上代码输入到  1.bat  文件里, 注意修改路径 ,代码中的 E 是盘符号

    2024年02月05日
    浏览(46)
  • 【微信小程序】JS文件内数组循环(批量)更新方法 图片批量增删

    学习微信小程序开发时遇到图片的批量增删问题,在分析了一些大佬的代码之后总结如下: 先定义一个临时数组承接已有的数组,进入循环用push来增加内容,或者用splice来删除内容,然后循环结束后,用setData把临时数组更新到原数组名下。 示例代码: 日拱一卒 功不唐捐

    2024年02月12日
    浏览(47)
  • 百度智能云对象存储BOS批量下载文件方法

    百度智能云对象存储BOS支持批量打包下载吗?目前对象存储BOS浏览器端不支持批量下载,可以使用对象存储BOS桌面或BOSCMD批量下载,也可以使用API/SDK调用接口循环下载。新手站长网来详细说下百度云对象存储BOS批量下载的方法: 目录 百度云对象存储BOS批量下载 BOS桌面客户端

    2023年04月20日
    浏览(34)
  • git拉取指定的单个或多个文件或文件夹

    直接上步骤 初始化仓库 拉取远程仓库信息,省略号为仓库地址 开启 sparse clone 配置需要拉取的文件夹 有一个指定一个,有多个指定多个,路径写对即可! 注意:路径问题,举例说明 路径位置要从项目的最开始文件夹开始,一级级往下配置。 5. 拉取仓库指定位置 注意 :指

    2023年04月11日
    浏览(49)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包