【JS】前端文件下载(无刷新)方法总结

摘要:
#传统方法利用iframe或form.submit或windows.open直接向后端发请求,后端返回文件流,后端处理成功后会直接返回到页面,浏览器会整理并打开自己的保存下载文件机制。FileName=test.txt";3variframe=document.createElement;4iframe.src=downloadURL;5iframe.style.display="none";6document.body.appendChild;7}2)后端代码:同上3)优缺点:优点:兼容性较好缺点:*html中会增加多余的iframe元素,增加了维护成本;*拿不到后端处理这个过程的时机,无法根据回调函数做交互以及进度提示;*URL长度有限制;3、使用windows.open下载文件1)前端代码1vardownloadURL="TestHandler.ashx?

#传统方法

利用iframe 或 form.submit 或 windows.open直接向后端发请求,后端返回文件流,后端处理成功后会直接返回到页面,浏览器会整理并打开自己的保存下载文件机制 。

1、利用form.submit直接向后端提交,后端返回文件流

1)前端代码:

1 var downloadURL = "RestHandle.ashx";
2 var testForm = $("<form>");   //定义一个form表单
3 testForm.attr('style','display:none');   //设置form表单属性
4 testForm.attr('target','');
5 testForm.attr('method','post');
6 testForm.attr('action',downloadURL);
7                     
8 var nameInput = $('<input>'); //构造formdata
9 nameInput.attr('type','hidden'); 
10 nameInput.attr('name','fileName'); 
11 nameInput.attr('value','test.txt');  
12  
13 $('body').append(testForm);  //将表单放置在web中
14 testForm.append(nameInput);   //将formdata添加到表单上
15 testForm.submit();   //表单提交
16 testForm.remove();  //表单移除

2)服务端代码,以asp.net为例:

1 public classTestHandler : IHttpHandler
2 {
3 
4     public voidProcessRequest(HttpContext context)
5 {
6         string fileName = context.Request["FileName"];//客户端传送过来的要下载的文件名
7         string filePath = System.Web.HttpContext.Current.Server.MapPath("DownLoad/" + fileName);//路径
8 
9         FileInfo newFile = newFileInfo(filePath);
10 
11         //以字符流的形式下载文件
12         FileStream fs = newFileStream(filePath, FileMode.Open);
13         byte[] bytes = new byte[(int)fs.Length];
14         fs.Read(bytes, 0, bytes.Length);
15 fs.Close();
16         context.Response.ContentType = "application/octet-stream";
17         //通知浏览器下载文件而不是打开
18         context.Response.AddHeader("Content-Disposition", "attachment;   filename=" +HttpUtility.UrlEncode(fileName, System.Text.Encoding.UTF8));
19 context.Response.BinaryWrite(bytes);
20 context.Response.Flush();
21 context.Response.End();
22 }
23 
24     public boolIsReusable
25 {
26         get
27 {
28             return false;
29 }
30 }
31 }

3)优缺点:

优点 :兼容性良好,传统方式,不会出现URL长度限制问题;

缺点:拿不到后端处理这个过程的时机,无法根据回调函数做交互以及进度提示

2、利于iframe直接向后端提交,后端返回文件流

1)前端代码:

1 functiondownFileByIframe(parameters) {
2     var downloadURL = "TestHandler.ashx?FileName=test.txt";
3     var iframe = document.createElement("iframe");
4     iframe.src =downloadURL;
5     iframe.style.display = "none";
6 document.body.appendChild(iframe);
7 }

2)后端代码:同上

3)优缺点:

优点: 兼容性较好

缺点: *html中会增加多余的iframe元素,增加了维护成本;

*拿不到后端处理这个过程的时机,无法根据回调函数做交互以及进度提示;

*URL长度有限制;

3、使用windows.open下载文件

1)前端代码

1 var downloadURL = "TestHandler.ashx?FileName=test.txt";
2 window.open(downloadURL);

2)后端代码:同上

3)优缺点:

优点: 兼容性良好,代码简洁;

缺点:*URL长度有限制;

*拿不到后端处理这个过程的时机,无法根据回调函数做交互以及进度提示;

4、解决“无法根据回调函数做交互”的问题:ajax提交,后端返回在线文件地址

利用ajax去提交请求,后端会返回一个线上的文件地址,前端可以通过原生的window.open打开这个地址就可以实现下载;

也可以通过a标签设置href以及download属性,并自动点击实现其下载功能,关于其兼容性问题,可以判断download属性是否存在来弥补。

1)优缺点:

优点 :可以拿到其返回时机,可以做交互;

缺点 :线上产生大量的中间临时文件,可以用设置时限来优化。解决方案:可使用大厂的云存储,从而减少临时文件的产生;

2)前端代码:

1 $.ajax({
2     type: "post",
3     url: "TestHandler.ashx",
4     data: {'FileName':'test.txt'},
5     success: function(res) {
6         if(res.Status) {
7             //window.open或者a标签下载 
8             var isSupportDownload = 'download' in document.createElement('a');
9             if(isSupportDownload) {
10                 var $a = $("<a>");
11 $a.attr({
12 href: res.url,
13                     download: 'filename'
14                 }).hide().appendTo($("body"))[0].click();
15             } else{
16 window.open(res.url)
17 }
18         } else{
19 alert(res.Message);
20 }
21 }
22 })

5、解决“无法根据回调函数做交互”的问题:jquery-download 插件

jquery.download.js插件github地址:https://github.com/johnculviner/jquery.fileDownload/blob/master/src/Scripts/jquery.fileDownload.js

jquery.download.js插件cdn地址:https://www.bootcdn.cn/jquery.fileDownload/

支持场景 : 与上面的几种方案相比,这个模块提供的方案更加完善,而不是局限于某种方案,相当于将上面的几种方案结合了起来, 使用率很高。在源码中,我们可以看到在这个模块中针对各个浏览器和相应的属性是否支持进行了比较全面的兼容。其对应的下载文件方案包括了以下几种。

  • window.open(url)打开某个文件地址
  • iframe的框架中,设置src属性,通过iframe进行文件的下载,支持文件地址
  • 通过form标签,设置action的文件地址,然后通过form的提交来完成文件的下载

1)前端代码:

1 var downloadURL = "TestHandler.ashx";
2 $.fileDownload(downloadURL, {
3     httpMethod: 'post',
4     data: { 'FileName': 'test.txt'},
5     prepareCallback: function(url) {
6         console.log("文件下载中...");
7         //数据加载动画
8         $("body").append('<div   style="background:url(images/load.png) top center no-repeat;"></div>');
9 },
10     abortCallback: function(url) {
11         //异常终止
12         console.log("文件下载异常!!");
13         $("#Loading").remove();
14 },
15     successCallback: function(url) {
16         console.log("文件下载成功!!");
17         $("#Loading").remove();
18 },
19     failCallback: function(html, url) {
20         console.log("文件下载失败!!");
21         $("#Loading").remove();
22 }
23 });

2)后端代码:

1 public voidProcessRequest(HttpContext context)
2 {
3     string fileName = context.Request["FileName"];//客户端保存的文件名
4     string filePath = System.Web.HttpContext.Current.Server.MapPath("DownLoad/" + fileName);//路径
5 
6     FileInfo newFile = newFileInfo(filePath);
7 
8     //以字符流的形式下载文件
9     FileStream fs = newFileStream(filePath, FileMode.Open);
10     byte[] bytes = new byte[(int)fs.Length];
11     fs.Read(bytes, 0, bytes.Length);
12 fs.Close();
13 
14     context.Response.ContentType = "application/octet-stream";
15     context.Response.AddHeader("Content-Disposition", "attachment;   filename=" +HttpUtility.UrlEncode(fileName, System.Text.Encoding.UTF8));
16 context.Response.BinaryWrite(bytes);
17 
18     //该cookie用于告诉jquery.fileDownload.js文件下载成功
19     context.Response.Cookies.Add(new HttpCookie("fileDownload", "true"));
20 context.Response.Flush();
21 context.Response.End();
22 }

注意: 这里的后端代码增加了一个名为“fileDownload”的cookie的返回;jquery.download.js插件使用该cookie来判断是否下载成功,从而进入成功回调函数(successCallback);

#新兴方案

1、利用Html5的download属性进行下载

1)前端代码

1 <a href="TestHandler.ashx?FileName=test.txt"download="test1.txt">DownloadAttrTest</a>

2)后端代码:同上

3)优缺点:

优点:代码简洁

缺点:存在浏览器兼容性的问题

4)参考:

https://www.zhangxinxu.com/wordpress/2016/04/know-about-html-download-attribute/

2、利用Html5的Blob对象实现对文件流进行下载

(1)、 使用原生js发送ajax实现

1)前端代码:

1 functiondownByBlob_1(parameters) {
2     var downloadURL = "TestHandler.ashx?FileName=zip.rar";
3     let xhr = newXMLHttpRequest()
4     let fileName = 'zip.rar' //文件名称 
5     xhr.open('GET', downloadURL, true);
6     xhr.responseType = 'arraybuffer';
7     //xhr.setRequestHeader('xx', 'xxxxx') // 请求头中添加信息
8     xhr.onload = function() {
9         if (this.status === 200) {
10             let type = xhr.getResponseHeader('Content-Type')
11 
12             let blob = new Blob([this.response], { type: type })
13             if (typeof window.navigator.msSaveBlob !== 'undefined') {
14                 /*
15 * IE workaround for "HTML7007: One or more blob URLs were revoked by closing
16 * the blob for which they were created. These URLs will no longer resolve as 
17 * the data backing the URL has been freed." 
18                  */
19 window.navigator.msSaveBlob(blob, fileName);
20             } else{
21                 let URL = window.URL ||window.webkitURL;
22                 let objectUrl =URL.createObjectURL(blob);
23 console.log(objectUrl);
24                 //"blob:http://localhost:10614/3e48b856-fca6-4e4c-b780-1c4a7066f42e"
25                 if(fileName) {
26                     var a = document.createElement('a');
27                     //safari doesn't support this yet
28                     if (typeof a.download === 'undefined') {
29                         window.location =objectUrl
30                     } else{
31                         a.href =objectUrl;
32                         a.download =fileName;
33 document.body.appendChild(a);
34 a.click();
35 a.remove();
36 }
37                 } else{
38                     window.location =objectUrl;
39 }
40 }
41 }
42 }
43 xhr.send();
44 }

2)后端代码:同上

(2)、 使用结合jq发送ajax请求实现,需要引入jquery.binarytransport.js插件,其扩展了jq的ajax的dataType的设置;

jquery.binarytransport.js插件github地址:https://github.com/henrya/js-jquery/tree/master/BinaryTransport

注意:当下载的是纯文本文件时,是不需要引入插件,ajax也不用配置dataType,直接用jq的ajax即可;

1)前端代码:

1 functiondownByBlob_2(parameters) {
2 $.ajax({
3         type: "post",
4         url: "TestHandler.ashx",
5         data: { 'FileName': 'zip.rar'},
6         dataType: 'binary',
7         responseType: 'arraybuffer',
8         success: function(msg) {
9             let blob = newBlob([msg]);
10 
11             console.log("Blob:" + msg); //msg 已不是乱码
12             let url =window.URL.createObjectURL(blob); 
13 
14             let a = document.createElement("a");
15 document.body.appendChild(a);
16             a.href =url;
17             a.download = 'zip.rar'; //命名下载名称
18             a.click(); //点击触发下载  
19             window.URL.revokeObjectURL(url); //下载完成进行释放
20 }
21 });
22 }

2)后端代码:同上

3)参考:  

http://www.henryalgus.com/reading-binary-files-using-jquery-ajax/

https://blog.csdn.net/aydongzhiping/article/details/82462473

3、新兴方案中的综合方案:file-saver

(1)、FileSaver.js 功能特点

  • FileSaver.js是一款基于HTML5完成文件保存的插件,它可以帮我们直接从网页中导出多种格式文件。
  • 同时对于那些本身不支持HTML5 W3C saveAs() FileSaver接口的浏览器,FileSaver.js也提供了支持。
  • 使用FileSaver.js可以让Web应用完美的生成文件,或者保存那些不应该发送到外部服务器的敏感信息。是一种简单易用的浏览器端文件保存方案。

(2)、安装

  FileSaver.js github地址:https://github.com/eligrey/FileSaver.js

可直接下载FileSaver.js 然后在页面中引用;

  npm、bower 安装:

npm install file-saver --save
bower install file-saver

(3)、demo:使用FileSaver.js下载后端返回的文件流;

1)前端代码:

1  functiondownByFileSaver(parameters) {
2     saveAs('TestHandler.ashx?FileName=zip.rar');
3 }

2)后端代码:同上

4、新兴方案的优缺点:

优点:技术新颖,某些场景下使用方便;

缺点:兼容性不好;

#参考

https://juejin.im/post/5bd5547a6fb9a05cdd2d5109

https://juejin.im/post/5bd1b0aa6fb9a05d2c43f004

https://www.cnblogs.com/yunser/p/7629399.html

https://blog.csdn.net/wt346326775/article/details/83617663

————————————————————————————————————————————————————

免责声明:文章转载自《【JS】前端文件下载(无刷新)方法总结》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇【论文笔记】Domain Adaptation via Transfer Component AnalysisDPDK 无锁队列Ring Library原理(学习笔记)下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

为博客园(或网站)添加百度分享按钮 自定义调用JS代码

1、百度分享代码调用地址 http://share.baidu.com/code 根据提示,一步一步的自定义选择,最后复制自定义好的样式,添加到WEB。 2、在页首Html代码中添加复制过来的JS代码 <!--baidu分享--> <script>window._bd_share_config={"common":{"bdSnsK...

VUE JS 闹钟函数

心跳函数:秒表 setInterval() 方法可按照指定的周期(以毫秒计)来调用函数或计算表达式。 setInterval() 方法会不停地调用函数,直到clearInterval()被调用或窗口被关闭。 由 setInterval() 返回的 ID 值可用作 clearInterval() 方法的参数。 clearInterval() 方法可取消由 s...

ElasticSearch应用之数据埋点——认识埋点

前言通过阅读本篇,你将获得以下三方面的知识: 什么是埋点? 埋点的用途? 埋点的分类? 一、什么是埋点所谓埋点就是在应用中特定的流程收集一些信息,用来跟踪应用使用的状况,后续用来进一步优化产品或是提供运营的数据支撑,包括访问数(Visits),访客数(Visitor),停留时长(Time On Site),页面浏览数(Page Views)和跳出率(Bo...

iframe中子父页面跨域通讯

目录 #跨域发送信息#window.postMessage()语法 #跨域接收信息 #示例Demo 在非跨域的情况下,iframe中的子父页面可以很方便的通讯,但是在跨域的情况下,只能通过window.postMessage()方法来向其他页面发送信息,其他页面要通过window.addEventListener()监听事件来接收信息; #跨...

layer弹出层框架alert与msg详解

layer至今仍作为layui的代表作,她的受众广泛并非偶然,而是这五年多的坚持,不断完善和维护、不断建设和提升社区服务,使得猿们纷纷自发传播,乃至于成为今天的Layui最强劲的源动力。目前,layer已成为国内最多人使用的web弹层组件,GitHub自然Stars3000+,官网累计下载量达30w+,大概有20万Web平台正在使用layer。    ...

AJAX技术框架及开发工具 转

常见的AJAX框架有: DWR - Web Remoting Buffalo - Web Remoting (based on prototype) prototype - JS OO library openrico - JS UI component (based on prototype) dojo - JS library and UI co...