javascript 进行多文件的下载
来源:互联网 发布:欧美女歌手 知乎 编辑:程序博客网 时间:2024/05/01 00:17
对于文件的下载,可以说是一个十分常见的话题,前端的很多项目中都会有这样的需求,比如 highChart 统计图的导出,在线图片编辑中的图片保存,在线代码编辑的代码导出等等。而很多时候,我们只给了一个链接,用户需要右键点击链接,然后选择“另存为”,这个过程虽说不麻烦,但还是需要两步操作,倘若用户想保存页面中的多个链接文件,就得重复操作很多次,最常见的就是英语听力网站上的音频下载,手都要点麻!
本文的目的是介绍如何利用 javascript 进行多文件的下载,也就是当用户点击某个链接或者按钮的时候,同时下载多个文件。这里的“同时”用的不是很准确,在现代浏览器中可以实现多文件的并行下载,而在一些老版本浏览器,如IE8-,此类的浏览器就只能进行单个文件的下载,但是我们可以让多个文件依次保存下来,算是串行下载吧~
若要要无视实现细节,可以直接跳到第三部分,或者戳:
代码封装:lib.js
DEMO:javascript-multiple-download (HTTPS,第三个有bug,具体原因下面有说明)
javascript-multiple-download (HTTP,测试正常)
本文地址:http://www.cnblogs.com/hustskyking/p/multiple-download-with-javascript.html,转载请保留原文地址。
一、文件类型介绍及其特点
1. 一般类型
平时比较常见的有 txt、png、jpg、zip、tar 等各种文件格式,这些文件格式中,一部分浏览器是会直接打开链接显示内容的,而另外一部分,浏览器不识别响应头,或者不能解析对应的格式,于是当做文件直接下载下来了。如:
这句代码,若直接点开链接,浏览器将会直接下载该文件。
2. dataURL类型
dataURL 也是十分常见的类型,他可以作为 src 或者 url() 的参数送进去。比较常见的有如下几种:
base64 是用的比较广泛的一种数据格式。
3. Blob 流
Blob 对象表示不可变的、包含原始数据的类文件对象。具体的内容可以参阅MDN文档。
他的使用也是特别的方便,如:
Blob 接收两个参数,一个是数组类型的数据对象,他可以是 ArrayBuffer、ArrayBufferView、Blob、String 等诸多类型;第二个参数是 MINE 类型设置。而本文我们要用到的是 URLcreateObjectURL()
这个函数,他的作用是将一个 URL 所代表的内容转化成一个DOMString,产生的结果是一个 文件对象 或者 Blob 对象。
4. 二进制流
我们利用 File API 读取文件的时候,拿到的是数据的二进制流格式,这些类型可以直接被 ArrayBuffer 等接收,本文中没有用到,就不细说了。
二、JavaScript 多文件下载
HTML5 中 a 标签多了一个属性——download,用户点击链接浏览器会打开并显示该链接的内容,若在链接中加了 download 属性,点击该链接不会打开这个文件,而是直接下载。虽说是比较好用,但低版本浏览器不兼容,这个在本节的 2 和 3 中将会讲到解决方案。
在这里,我们可以利用 属性检测 UA 来判断浏览器类型:
1. a 标签 download 属性的使用
注:FF5.0 / Safari5.0 / Opera11.1 / IE9.0 不支持 download 属性
利用 download 属性可以直接下载单个文件,若想点击一次下载多个文件,就得稍加处理下了:
download 属性的作用除了让浏览器忽略文件的 MIME 类型之外,还会把该属性的值作为文件名。你可以在 chrome 控制台运行这句程序:
浏览器会提示是否保留(下载)该 html 文件。之前我们提到文件类型还可能是 dataURL 或者是 Blob 流,为了让程序也支持这些数据类型,稍微修改下上面的函数:
new Blob([content])
,现将文件转换成一个 Blog 流,然后,使用 URL.createObjectURL()
将其转换成一个 DOMString。这样我们就支持 data64 和其他数据类型的 content 了~
2. window.open 之后 execCommand("SaveAs")
上面也提到了,尽管 download 属性是十分便利的 H5 利器,但低版本 IE 根本不赏脸,要说方法,IE 还是有很多方式去转换的,比如 ADOBE.STREAM 的 activeX 对象可以把文件转换成文件流,然后写入到一个要保存的文件中。这里要谈到的是略微方便一点的方式:先把内容写到一个新开的 window 对象中,然后利用 execCommand 执行保存命令,就相当于我们在页面上按下 Ctrl+S,这样页面内的信息都会 down 下来。
这个过程十分明了,不过这里会存在一个问题,并不是程序的问题,而是浏览器的问题,如果我们用 搜狗浏览器 或者 360浏览器 打开新窗口的话,他会新开一个标签页,而不是新开一个窗口,更可恶的是部分浏览器拦截 window.open 的窗口(这个可以设置)。所以只好另觅他法了。
3. iframe 中操作
既然新开一个窗口那么麻烦,我就在本窗口下完成工作~
一般的链接我们可以直接给 iframe 添加 src 属性,然后执行 saveAs 命令,倘若我们使用的是 data64 编码的文件,这个怎么办?
这个也比较好处理,直接把文件写入到 iframe 中,然后在执行保存。
三、代码的封装与接口介绍
1. 代码的封装以及相关 DEMO
封装:lib.js
DEMO:javascript-multiple-download (HTTPS,第三个有bug)
javascript-multiple-download (HTTP,测试正常)
Bug 说明,经过一番细节处理之后,基本兼容各个浏览器,我把代码放在 https://raw.github.com 上托管,可能因为是 https 传输,第三个测试中报错了,报错的具体内容是:HTTPS 安全受到 http://rawgithub.com/barretlee/javascript-multiple-download/master/file/test.jpg 的威胁,而 test.txt 文件没有报错。放到 http 协议下测试运行结果是可观的。(这点我没有去深究,肯定是有深层安全方面原因的,难道就因为他是 jpg图片格式? 谢 @屈屈 提醒,跨协议传输存在安全问题)后面的 demo 我放在 BAE 上,没有问题,不过没测试 safari 和 opera。
2. 接口的调用
提供了三个接口,支持单文件下载,多文件下载,多文件下载自定义命名。
1)单文件下载
2)多文件下载
3)多文件下载自定义命名
文件的 URL 如 ./file/test.jpg
都可以改成 base64 或者其他格式,如:
这里只做到了 chrome 兼容,IE 下懒得去看了,这个需求很少见!
四、服务器支持与后端实现
1. 后端实现
不使用前端,直接后端实现的原理,就是在响应头中加入一些特殊的标记,如前端发送这样的请求:
后端的响应为
告诉浏览器这是一个流文件,作为附件方式发送给你,请忽略 MINE type,直接保存。
2. 服务器配置
若后台是 apche 作为服务器,可以配置 htaccess 文件:
意思是只要请求的是 zip 或者 rar 类型的文件,那么就添加一个 Content-Disposition:attachment
的响应头。这样就可以在 php 代码中省略麻烦的操作。
五、IE浏览器下载文件
function download(){var downloadUrl="template/模板.xlsx";downloadUrl=encodeURIComponent(downloadUrl); //用了2次encodeURI //这个打开了新的窗口//window.open(downloadUrl,"_blank", "width=0, height=0,status=0"); window.location.href=downloadUrl;}
六、小结
由于行文仓促,文中会有不少错误,对多文件下载有更好的提议,希望提出来共同分享!
实现多文件下载的方式肯定不止上面提到的几种,而且我这里封装的代码并没有在FF safari opera 中实现,因为他们还没兼容 download 属性,具体情况可以查看 caniuse 。建议在项目中把这样的事情交给后端,几句代码可以搞定。
七、参考资料
- 在浏览器端用JS创建和下载文件 AlloyTeam
- Starting file download with Javascript Ahzaz's Blog
- Blob 流 MDN
- javascript 进行多文件的下载
- struts2进行文件的下载
- Servlet中进行文件下载的写法
- servlet进行文件的上传和下载
- 使用DWR3.0进行文件的下载
- 用struts1进行文件的下载
- 使用XUtils进行文件的断点下载
- 利用FNDLOAD进行ldt文件的下载
- javascript下载文件
- javascript文件下载代码
- Javascript创建文件下载
- 使用 JavaScript 下载文件
- 使用Loadrunner进行文件的上传和下载
- 使用Struts2框架进行文件的上传与下载
- 关于使用jspsmartupload.jar进行文件的上传与下载
- 使用Apache POI WorkBook 进行下载文件的一个问题
- 使用Loadrunner进行文件的上传和下载
- Java使用SmartUploadServlet进行文件的上传与下载
- 第十四周项目3——是否二叉排序树?
- git push code: merge pending
- 欢迎使用CSDN-markdown编辑器
- v4l2基础学习二
- 51Nod 1202 子序列个数
- javascript 进行多文件的下载
- mysql存储过程详解
- 数组去重
- 命令行编译Qt程序
- Eclipse/IDEA使用小技巧
- 第十三周项目四(Floyd算法实现)
- Android Cordova 插件开发之创建项目
- 【Android应用开发】RecycleView API 翻译 (文档翻译)
- 自己编写的Spring4.x教程可以下载了