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

智能推荐

高数总结(微分方程)_高数微分方程-程序员宅基地

文章浏览阅读3.4w次,点赞28次,收藏113次。1)微分方程:未知函数,未知函数的导数,自变量;2)微分的阶:最高阶导数的次数;3)可分离变量的微分方程:g(y)dy=f(x)dx型,这类微分方程的解法是两边同时积分;需要注意的是,虽然可以化为这种类型,但不一定能求出解的。4)齐次微分方程:可化为dy/dx=G(y/x)的方程。可令u=y/x,并变换成可分离变量的微分方程来求解;5)可化为齐次微分方程:dy/dx=(ax+by+c)/(lx+m_高数微分方程

深度前馈神经网络之深度神经网络(DNN)总结_dnn深度神经网络-程序员宅基地

文章浏览阅读6.6k次,点赞5次,收藏28次。概览多层感知机(MLP)和深度神经网络(DNN)是一样的模型,只是叫法不同。深度神经网络,卷积神经网络(CNN)都属于深度前馈神经网络(DFNN)。一、连接方式连接方式分为两种全连接,MLP采用,当前层的单元与上一层的每一个单元都有连接。稀疏连接,CNN采用,当前层的单元只与上一层的部分单元有连接。..._dnn深度神经网络

【系统集成项目管理工程师】2021年5月上午+下午真题及答案解析_2021年系统集成5月份真题-程序员宅基地

文章浏览阅读2.1k次。软考大讲堂2021年上半年【系统集成项目管理工程师】真题答案已发布!帮助大家在线免费估分,“提前”知晓分数!_2021年系统集成5月份真题

wince 德赛西威2413_德赛西威NAV230凯立德2016春季专版C2134-C7M07-3921J0S-程序员宅基地

文章浏览阅读772次。这是德赛西威NAV230凯立德2016春季专版C2134-C7M07-3921J0S,这款最新的专版为凯立德2016春季版,版本号:C2134-C7M07-3921J0S,分辨率为高清800*480,端口及分辨率为常用的COM2 9600。软件介绍德赛西威NAV230专用的凯立德导航地图又更新啦!凯粉们还在等什么。这款最新的专版为凯立德2016春季版,版本号:C2134-C7M07-3921J0S..._德赛西威地图下载

浅析virtio技术(2)virtio设备管理_virtio header-程序员宅基地

文章浏览阅读1.1k次。virtio协议定义了virtio通信遵循的接口,包含设备状态、设备支持的特性以及前后端数据传输的通道(virtqueue)。目前在使用的virtio规范有三个版本0.95、1.0和1.1。0.95版本是目前广泛在使用的版本,称为传统模式;1.0版本中协议将设备的配置部分做了一些调整,被称为现代模式;1.1版本则主要是新增了packedvirtqueue的支持。本文重点关注于virtio设备相关的规范定义。..._virtio header

研究:利用古代玉米基因组推断美国玉米群体演化历史(Science 2017)_parviglumis-程序员宅基地

文章浏览阅读1.7k次。Genomic estimation of complex traits reveals ancient maize adaptation to temperate North America,Kelly Swarts ,Rafal M. Gutaker,Detlef Weigel,Edward S. Buckler,Hernán A. Burbano,Science,4 Aug 2017 ,DOI: 10.1126/science.aam9425本文的特殊材料是 15 个古代玉米样本的基因组数据,._parviglumis

随便推点

mvn的简单使用_mvn locale-程序员宅基地

文章浏览阅读3.8k次。maven2安装说是安装其实就是下载相关的bin包就可以了1、首先去官方网站下载之:[url]http://maven.apache.org/download.html[/url],我选择的是截至目前最新版本maven3.0.4版本2、设置环境变量:Maven2下载完后,我将其解压到我的计算机的d:\maven304下,目录结构如下:D:\|--Maven204|--_mvn locale

webkit、blink、chromium、chrome关系_为什么新版的谷歌浏览器还是显示的webkit而不是blink-程序员宅基地

文章浏览阅读2k次。最近在browser/web开发中遇到的一些概念v8、mozjs、spidermonkeywebkit、gecko、trident、blinkchrominum、chrome、Safri、IE、Mozilla、Android Browser总结了它们之间的关系:Mozjs是SpiderMonley的具体实现方式。Chrome在Chromium上新增了一些Go..._为什么新版的谷歌浏览器还是显示的webkit而不是blink

springboot基础入门-程序员宅基地

文章浏览阅读399次。1.基础入门1、spring与springbootspringspring能做什么如下:微服务、响应式、云、web应用、无服务架构(类似java里的函数式编程)、批处理spring的生态具体请看链接https://spring.io/projects/spring-boot覆盖了:web开发、数据访问、安全控制、分布式、消息服务、移动开发、批处理spring5重大升级1.响应式编程左边响应式栈、右边Servlet栈2.内部源码设计更新基于Java8的一些新特性,spring也

使用python采集股票实时行情_python 全市场股票实时行情-程序员宅基地

文章浏览阅读79次。【代码】使用python采集股票实时行情。_python 全市场股票实时行情

卡顿分析:掉帧_layoutmanager 耗时卡顿-程序员宅基地

文章浏览阅读1.7k次,点赞2次,收藏2次。前言:Android中标准帧率是60FPS,每秒刷新60帧画面,那么每帧就要在大约16ms渲染完成,如果超过了16ms,就会仍然显示上一帧画面。对于用户来说就是界面被卡住了。尤其是在连续的滑动过程中,突然掉帧,对用户来说卡顿非常明显,体验很不好。反而如果刷新一直保持在一个稳定的帧率,对用户体验来说反而影响不大,比如王者荣耀的最高帧率也就30FPS,但是由于我们的眼睛对于24fps就已经感觉到流畅..._layoutmanager 耗时卡顿

Centos 7源码安装mariadb10.4.13_mariadb10.4 aarh-程序员宅基地

文章浏览阅读522次。一、环境[root@localhost mariadb-10.4.13]# ifconfig |grep 192.168 inet 192.168.1.107 netmask 255.255.255.0 broadcast 192.168.1.255[root@localhost mariadb-10.4.13]# cat /etc/redhat-release CentOS Linux release 7.7.1908 (Core)[root@localhost mariadb_mariadb10.4 aarh

推荐文章

热门文章

相关标签