js前端自动下载文件(无刷新)_js createobjecturl 批量下载文件-程序员宅基地

技术标签: 杀软主动防御  

目录

 

正文

#传统方法

利用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 class TestHandler : IHttpHandler
 2 {
 3 
 4     public void ProcessRequest(HttpContext context)
 5     {
 6         string fileName = context.Request["FileName"];//客户端传送过来的要下载的文件名
 7         string filePath = System.Web.HttpContext.Current.Server.MapPath("DownLoad/" + fileName);//路径
 8 
 9         FileInfo newFile = new FileInfo(filePath);
10 
11         //以字符流的形式下载文件
12         FileStream fs = new FileStream(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 bool IsReusable
25     {
26         get
27         {
28             return false;
29         }
30     }
31 }

复制代码

  3)优缺点:

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

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

 

回到顶部

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

  1)前端代码:

复制代码

1 function downFileByIframe(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 id="Loading" 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 void ProcessRequest(HttpContext context)
 2 {
 3     string fileName = context.Request["FileName"];//客户端保存的文件名
 4     string filePath = System.Web.HttpContext.Current.Server.MapPath("DownLoad/" + fileName);//路径
 5 
 6     FileInfo newFile = new FileInfo(filePath);
 7 
 8     //以字符流的形式下载文件
 9     FileStream fs = new FileStream(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 function downByBlob_1(parameters) {
 2     var downloadURL = "TestHandler.ashx?FileName=zip.rar";
 3     let xhr = new XMLHttpRequest()
 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 function downByBlob_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 = new Blob([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  function downByFileSaver(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

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/zy_strive_2012/article/details/107119556

智能推荐

职称计算机在线模拟考试,2017职称计算机考试Windows模拟试题-程序员宅基地

文章浏览阅读256次。2017职称计算机考试Windows模拟试题习题的练习有利于知识点的复习,下面是小编给大家提供的职称计算机考试Windows模拟试题,大家可以参考练习,更多习题练习请关注应届毕业生考试网。1 Windows"回收站"中不可能有 。答案: DA 文件夹B 硬盘中的文件C 快捷方式D 软盘中的文件2 在windows资源管理器中,当前文件夹为D;\考试,选择其中的文件A.DOC,按住Shift键,用鼠..._在windows10操作环境下,文件命名错误的是

语音识别ASR背后的原理_asr算法识别静音是怎恶魔做到的-程序员宅基地

文章浏览阅读967次,点赞10次,收藏19次。语音识别技术(Automatic Speech Recognition)是一种将人的语音转换为文本的技术。_asr算法识别静音是怎恶魔做到的

第五章 微服务框架-Spring Boot、Spring Cloud_springboot微服务-程序员宅基地

文章浏览阅读526次。随着动态语言的流行(Ruby、Groovy、 Scala、 Node.js) ,Java的开发显得格外的笨重繁多的配置、低下的开发效率、复杂的部署流程以及第三方技术集成难度大。在上述环境下,Spring Boot应运而生。它使用“习惯优于配置”(项目中存在大量的配置,此外还内置了一个习惯性的配置 ,让你无需手动进行配置)的理念让你的项目快速的运行起来。_springboot微服务

如何查看数据包路由和转发情况_看发送的数据包的转发过程-程序员宅基地

文章浏览阅读1.7k次。tcpdump是一个强大的网络分析工具,可以捕获和分析网络流量。它可以应用于任何网络接口,包括veth、bridge等设备。例如,你可以使用以下命令来捕获在某个veth设备上的流量:其中vethXXX是你想要观察的veth设备的名称。: ip命令是一个多功能的网络配置工具。你可以使用它来查看网络设备、路由表、ARP表等信息。例如,你可以使用以下命令来查看veth设备的状态:你还可以使用以下命令来查看路由表:: netstat命令可以显示网络连接、路由表、接口统计等信息。_看发送的数据包的转发过程

计算两个经纬度点之间的距离_getdistance求经纬度之间的距离-程序员宅基地

文章浏览阅读1.2k次。计算经纬度点之间距离的算法 getDistance(lat1, lng1, lat2, lng2) { const radLat1 = lat1 * Math.PI / 180.0; const radLat2 = lat2 * Math.PI / 180.0; const a = radLat1 - radLat2; con..._getdistance求经纬度之间的距离

Unity + Grpc + protobuf + C# 使用流程详解_unity grpc-程序员宅基地

文章浏览阅读3.7k次,点赞11次,收藏30次。最近公司的一个unity项目要把通信方式从Photon替换成grpc,正好系统学一下grpc,以下是我的学习心得。本篇博客系统详细地介绍了unity使用grpc通信的全部要点,希望可以帮助到大家。奥利给!详解目录一、本篇博客知识点简介二、资源及工具的下载地址1、protocolBuffer各个版本2、GRPC3、grpc_unity_package.2.27.0-dev4、.NET Core SDK 2.1及以上三、C#使用Grpc方法流程1、新建项目2、定义服务3、使用GRPC.Tools自动生成.c_unity grpc

随便推点

记录一次kafka内存溢出,消费慢_kafka消费导致内存泄露-程序员宅基地

文章浏览阅读1k次。记录一次kafka内存溢出,消费慢_kafka消费导致内存泄露

前端学习week9-程序员宅基地

文章浏览阅读933次,点赞12次,收藏29次。数据存储在用户浏览器中设置、读取方便、甚至页面刷新不丢失数据容量较大,sessionStorage和localStorage约5M左右正则表达式是用于匹配字符串中正负组合的模式。在JavaScript中,正则表达式也是对象,通常用来查找、替换哪些符合正则表达式的文本作用:表单验证、过滤敏感词、字符串中提取我们想要的部分const 变量名 = /表达式/其中/ /是正则表达式字面量基于VueCli自定义创建项目架子安装脚手架创建项目。

解决syszuxpinyin重复点击lineEdit无法弹出输入法界面和无法删除原有内容问题_qlineedit输入中文无法删除-程序员宅基地

文章浏览阅读2.1k次。解决方法均来源于论坛,自己把它给整理一下1,因为自己做的界面用到了lineedit,但是发现第一次点击lineedit获得焦点就可以弹出输入法界面,但是再重复点击的时候就不能弹出来了,必须重新获得焦点,于是通过重载重载了QLineEdit的mousePressEvent在mousePressEvent加上一个自定义的信号 emit clicked()重载代码如下:mylineedi_qlineedit输入中文无法删除

jeb 下载-程序员宅基地

文章浏览阅读1k次。jeb-1.5.201408040(full)_keygen_by_scz(20150725) http://scz.617.cn/ 修改jeb_wincon.bat 中java home 变量,然后就可以启动 注册机 java kegen_jeb下载 csdn

python绿色参数_Python进阶三部曲之IO操作-程序员宅基地

文章浏览阅读60次。IO编程文件读写打开文件open(file, mode='r', buffering=None, encoding=None, errors=None, newline=None, closefd=True) 具体需要查看API,这里只介绍几个常用的方法。open函数的文件名是必传参数,返回一个文件对象#打开一个文件。f = open('read.txt', 'r')open函数的mode参数:值..._python程序里面传进去的参数是绿色

高通平台8953 Linux DTS(Device Tree Source)设备树详解之一(背景基础知识篇)_高通提取dtb-程序员宅基地

文章浏览阅读5.8k次,点赞3次,收藏61次。本系列导航:高通平台8953 Linux DTS(Device Tree Source)设备树详解之一(背景基础知识篇)高通平台8953 Linux DTS(Device Tree Source)设备树详解之二(DTS设备树匹配过程)高通平台8953 Linux DTS(Device Tree Source)设备树详解之三(高通MSM8953 android7.1实例分析篇)一.什么是DTS?为..._高通提取dtb