目录
正文
利用iframe 或 form.submit 或 windows.open直接向后端发请求,后端返回文件流,后端处理成功后会直接返回到页面,浏览器会整理并打开自己的保存下载文件机制 。
回到顶部
1)前端代码:
1 var downloadURL = "RestHandle.ashx";2 var testForm = $(""); //定义一个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 = $(''); //构造formdata9 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 : IHttpHandler2 {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长度限制问题;
缺点:拿不到后端处理这个过程的时机,无法根据回调函数做交互以及进度提示
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长度有限制;
1)前端代码
1 var downloadURL = "TestHandler.ashx?FileName=test.txt";
2 window.open(downloadURL);
2)后端代码:同上
3)优缺点:
优点: 兼容性良好,代码简洁;
缺点: *URL长度有限制;
*拿不到后端处理这个过程的时机,无法根据回调函数做交互以及进度提示;
利用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 = $("");
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 })
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/
支持场景 : 与上面的几种方案相比,这个模块提供的方案更加完善,而不是局限于某种方案,相当于将上面的几种方案结合了起来, 使用率很高。在源码中,我们可以看到在这个模块中针对各个浏览器和相应的属性是否支持进行了比较全面的兼容。其对应的下载文件方案包括了以下几种。
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('');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)前端代码
2)后端代码:同上
3)优缺点:
优点:代码简洁
缺点:存在浏览器兼容性的问题
4)参考:
https://www.zhangxinxu.com/wordpress/2016/04/know-about-html-download-attribute/
(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
(1)、FileSaver.js 功能特点
(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)后端代码:同上
回到顶部
优点:技术新颖,某些场景下使用方便;
缺点:兼容性不好;
fetch('https://jsonplaceholder.typicode.com/todos/1').then(resp => resp.blob()).then(blob => {const url = window.URL.createObjectURL(blob);const a = document.createElement('a');a.style.display = 'none';a.href = url;// the filename you wanta.download = 'todo-1.json';document.body.appendChild(a);a.click();window.URL.revokeObjectURL(url);alert('your file has downloaded!'); // or you know, something with better UX...}).catch(() => alert('oh no!'));
后端代码同上
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