热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

前端文件下载方式方法总结

目录1、利用form.submit直接向后端提交,后端返回文件流2、利于iframe直接向后端提交,后端返回文件流3、使用windows.open下载文件4、解决“无法根据回调函

目录

  • 1、利用form.submit直接向后端提交,后端返回文件流
  • 2、利于iframe直接向后端提交,后端返回文件流
  • 3、使用windows.open下载文件
  • 4、解决“无法根据回调函数做交互”的问题:ajax提交,后端返回在线文件地址
  • 5、解决“无法根据回调函数做交互”的问题:jquery-download 插件
  • 1、利用Html5的download属性进行下载
  • 2、利用Html5的Blob对象实现对文件流进行下载
    • (1)、 使用原生js发送ajax实现
    • (2)、 使用结合jq发送ajax请求实现,需要引入jquery.binarytransport.js插件,其扩展了jq的ajax的dataType的设置;
  • 3、新兴方案中的综合方案:file-saver
    • (1)、FileSaver.js 功能特点
    • (2)、安装
    • (3)、demo:使用 FileSaver.js下载后端返回的文件流;
  • 4、新兴方案的优缺点:

正文

#传统方法

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

回到顶部

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

  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长度限制问题;

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

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 = $("");
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('

');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)前端代码

DownloadAttrTest

  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、新兴方案的优缺点:

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

  缺点:兼容性不好;

5.使用 Javascript API -- fetch 实现文件下载功能


 前端代码:

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


推荐阅读
  • 本文探讨了2019年前端技术的发展趋势,包括工具化、配置化和泛前端化等方面,并提供了详细的学习路线和职业规划建议。 ... [详细]
  • golang常用库:配置文件解析库/管理工具viper使用
    golang常用库:配置文件解析库管理工具-viper使用-一、viper简介viper配置管理解析库,是由大神SteveFrancia开发,他在google领导着golang的 ... [详细]
  • 本文探讨了领域驱动设计(DDD)的核心概念、应用场景及其实现方式,详细介绍了其在企业级软件开发中的优势和挑战。通过对比事务脚本与领域模型,展示了DDD如何提升系统的可维护性和扩展性。 ... [详细]
  • 本文介绍了多个关于JavaScript的书籍资源、实用工具和编程实例,涵盖从入门到进阶的各个阶段,帮助读者全面提升JavaScript编程能力。 ... [详细]
  • 本文探讨了浏览器的同源策略限制及其对 AJAX 请求的影响,并详细介绍了如何在 Spring Boot 应用中优雅地处理跨域请求,特别是当请求包含自定义 Headers 时的解决方案。 ... [详细]
  • 本文详细介绍如何使用Python进行配置文件的读写操作,涵盖常见的配置文件格式(如INI、JSON、TOML和YAML),并提供具体的代码示例。 ... [详细]
  • 深入理解Tornado模板系统
    本文详细介绍了Tornado框架中模板系统的使用方法。Tornado自带的轻量级、高效且灵活的模板语言位于tornado.template模块,支持嵌入Python代码片段,帮助开发者快速构建动态网页。 ... [详细]
  • MySQL 数据库迁移指南:从本地到远程及磁盘间迁移
    本文详细介绍了如何在不同场景下进行 MySQL 数据库的迁移,包括从一个硬盘迁移到另一个硬盘、从一台计算机迁移到另一台计算机,以及解决迁移过程中可能遇到的问题。 ... [详细]
  • 探讨在循环中调用$.post()时,回调函数为何会在循环结束后才开始执行,并提供解决方案和优化建议。 ... [详细]
  • Python处理Word文档的高效技巧
    本文详细介绍了如何使用Python处理Word文档,涵盖从基础操作到高级功能的各种技巧。我们将探讨如何生成文档、定义样式、提取表格数据以及处理超链接和图片等内容。 ... [详细]
  • 本文探讨了如何利用HTML5和JavaScript在浏览器中进行本地文件的读取和写入操作,并介绍了获取本地文件路径的方法。HTML5提供了一系列API,使得这些操作变得更加简便和安全。 ... [详细]
  • 本文深入探讨了JavaScript中实现继承的四种常见方法,包括原型链继承、构造函数继承、组合继承和寄生组合继承。对于正在学习或从事Web前端开发的技术人员来说,理解这些继承模式对于提高代码质量和维护性至关重要。 ... [详细]
  • 本文将详细介绍如何在ThinkPHP6框架中实现多数据库的部署,包括读写分离的策略,以及如何通过负载均衡和MySQL同步技术优化数据库性能。 ... [详细]
  • ServletContext接口在Java Web开发中扮演着重要角色,它提供了一种方式来获取关于整个Web应用程序的信息。通过ServletContext,开发者可以访问初始化参数、共享数据以及应用资源。 ... [详细]
  • 本文深入探讨网页游戏的开发流程,涵盖从程序框架设计到具体实现的技术细节,旨在为开发者提供全面的指导。 ... [详细]
author-avatar
a734839433
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有