前端实现文件下载常用几种方式

项目中前端下载一般分为两种情况:

  • 后端直接提供一个文件地址,通过浏览器打开就可以下载。
  • 需要发送请求,后端返回二进制流数据,前端解析流数据,生成URL实现下载。

前端对应的实质是a标签和Blob文件下载,这两者的区别:

a标签:txt、png、jpg、gif等文件,是不提供直接下载,有兼容性问题,特别是IE。
blob:利用 Blob对象可以将文件流转化成 Blob二进制对象。该对象兼容性良好,适用于需要动态生成或处理非同源文件的情况。‌通过URL.createObjectURL()方法将Blob对象转换为一个临时的URL下载。
blob对象
Blob对象表示一个不可变、原始数据的类文件对象。它的数据可以按文本或二进制的格式进行读取,也可以转换成 ReadableStream来用于数据操作。Blob对象是html5新增的对象,它的作用是用来存储二进制数据的,比如图片、视频、音频等,

属性

  • size:只读属性,Blob中的字节数。
  • type:只读属性,表示Blob存放的媒体类型,图片、视频、文本文件等等。
  • 它的使用方法如下:

blob对象

Blob对象表示一个不可变、原始数据的类文件对象。它的数据可以按文本或二进制的格式进行读取,也可以转换成 ReadableStream来用于数据操作。Blob对象是html5新增的对象,它的作用是用来存储二进制数据的,比如图片、视频、音频等,

属性

  • size:只读属性,Blob中的字节数。
  • type:只读属性,表示Blob存放的媒体类型,图片、视频、文本文件等等。
    它的使用方法如下:
const blob = new Blob([], { type: '' });

URL.createObjectURL
URL.createObjectURL()静态方法会创建一个DOMString,其中包含一个表示参数中给出的对象的URL。这个URL的生命周期和创建它的窗口中的document绑定。这个新的URL对象表示指定的File对象或Blob对象。
当我们的document被销毁后,这个URL就会失效,所以我们需要在合适的时机销毁它。

简单说这个方法用来创建一个url的,它的作用是把一个blob对象转换成一个url,这个url可以用来下载文件,也可以用来预览文件。

// 创建下载的链接
const url = URL.createObjectURL(blob);
// 释放掉blob对象
URL.revokeObjectURL(url);

传统a标签下载

const a = document.createElement('a'); // 创建a标签
a.style = 'display: none';
a.download = filename''; // 设置下载文件名
a.href = url; // 设置下载地址
document.body.appendChild(a);
a.click(); // 触发a标签的click事件
document.body.removeChild(a);

这种方式无法解决浏览器可识别文件直接打开的问题,但是 HTML5 新属性 download 属性会解决这个问题。

a标签 + download属性
当URL是同源(同域名、同协议、同端口号)时,这种情况用 a标签加download属性的方式即可,download属性指示浏览器该下载而不是打开该文件,同时该属性值即下载时的文件名;

<a href="path/to/file.jpg" download='file.jpg'>点击下载图片</a>
const a = document.createElement('a'); // 创建a标签
const e = document.createEvent('MouseEvents'); // 创建鼠标事件对象
e.initEvent('click', false, false); // 初始化事件对象
a.href = url; // 设置下载地址
a.download = filename || ''; // 设置下载文件名
a.dispatchEvent(e);

因为a标签下载只能下载同源的文件,如果是跨域的文件,这里包括图片、音视频等媒体文件,都是预览,也无法下载。

fetch发送请求
通过原生fetch请求,动态生成一个a标签实现文件下载。
res.blob()该方法是Fetch API的response对象方法,该方法将后端返回的文件流转换为返回blob的Promise;blob(Binary Large Object)是一个二进制类型的对象,记录了原始数据信息。
URL.createObjectURL(blob)该方法的返回值可以理解为一个指向传入参数对象的url可以通过该url访问参数传入的对象。

// 将url转成blob地址
fetch(url).then(res => res.blob()).then(blob => {const a = document.createElement('a');// 将链接地址字符内容转变成blob地址a.href = URL.createObjectURL(blob);a.download = filename; // 下载文件的名字document.body.appendChild(a);a.click();// 下载完成后 清除占用的缓存资源window.URL.revokeObjectURL(a.href);document.body.removeChild(a);});
  • 该方法需要注意的是,即便传入同一个对象作为参数,每次返回的url对象都是不同的。
  • 该url对象保存在内存中,只有在当前文档(document)被卸载时才会被清除,因此为了更好的性能,需要通过URL.revokeObjectURL(blobUrl)主动释放。

XMLHttpRequest
XMLHttpRequest(‌简称XHR)‌是一个用于创建服务器之间通信的Web API。‌在下载文件时,‌可以通过设置responseType为blob来接收二进制数据。‌这种方法适用于需要从服务器获取文件流并进行下载的场景。‌与Blob类似,‌XHR也可以用于动态生成文件并触发下载,‌但它在处理异步请求和数据传输方面提供了更多的灵活性。‌

可通过xhr.setRequestHeader设置请求头参数。
可通过xhr.getResponseHeader(‘content-disposition’)获取头部参数。
 

let xhr = new XMLHttpRequest();
// GET请求,downloadURL请求路径url,async(是否异步)
xhr.open('GET', downloadURL, true);
// 设置请求头参数的方式,如果没有可忽略此行代码
xhr.setRequestHeader("Token", 'Bearer ' + getStorage().token); // token
// 设置响应类型为 blob
xhr.responseType = 'blob';
// 关键部分
xhr.onload = function () {//如果请求执行成功if (this.status === 200) {// 下载文件const blob = new Blob(this.response);const href = window.URL.createObjectURL(blob); // 创建下载的链接const a = document.createElement('a');a.href = href;a.download = fileName; // 下载文件名document.body.appendChild(a);a.click(); // 点击下载document.body.removeChild(a); // 下载完成移除元素window.URL.revokeObjectURL(href); // 释放掉blob对象// 可通过xhr.getResponseHeader('content-disposition')头部参数,文件名等// let headerParams = xhr.getResponseHeader('content-disposition')?.split(";") || [];}
};
// 发送请求
xhr.send();
xhr.onreadystatechange = function () { if (xhr.readyState === 4 && xhr.status === 200) { // 成功后操作 } 
};

axios请求方式

axios({method: method ||'post',url,responseType: 'blob',headers: {'Content-Type': 'application/json; charset=utf-8'// 可在此处添加请求参数token: 'token值'}data: JSON.stringify(params)
}).then(res => {if (res) {const blob = new Blob(res);const url = window.URL.createObjectURL(blob)const a = document.createElement('a')a.style.display = 'none'a.href = href;a.download = fileName; // 下载文件名document.body.appendChild(link)link.click()document.body.removeChild(link); // 下载完成移除元素window.URL.revokeObjectURL(url); // 释放掉blob对象} else {message.error('下载失败')return;}
})

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/60222.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

设计模式之责任链模式(Chain Of Responsibility)

一、责任链模式介绍 1、责任链模式介绍 职责链模式(chain of responsibility pattern) 定义: 避免将一个请求的发送者与接收者耦合在 一起&#xff0c;让多个对象都有机会处理请求。将接收请求的对象连接成一条链&#xff0c;并且沿着这条链 传递请求&#xff0c;直到有一个对…

C语言中的 printf( ) 与 scanf( )

时隔多日&#xff0c;小编我又回来咯小编相信之前的博客能够给大家带来不少的收获。在我们之前的文章中&#xff0c;许多代码块的例子都用到了printf( ) 与 scanf( )这两个函数&#xff0c;大家都知道他们需要声明头文件之后才能使用&#xff0c;那这两个函数是什么呢&#xff…

数字乡村解决方案-1

1. 政策背景与新时代党建 党的十九大报告提出新时代党建总要求&#xff0c;强调乡村治理在国家治理体系中的重要性&#xff0c;并作为实现乡村振兴战略的基石。提出按照产业兴旺、生态宜居、乡风文明、治理有效、生活富裕的总要求&#xff0c;推进乡村治理体系和治理能力现代化…

栈和队列相关题 , 用队列实现栈, 用栈实现队列 ,设计循环队列 C/C++双版本

文章目录 1.用队列实现栈2.用栈实现队列3. 设计循环队列 1.用队列实现栈 225. 用队列实现栈 思路&#xff1a; 使用两个队列&#xff0c;始终保持一个队列为空。 当我们需要进行压栈操作时&#xff0c;将数据压入不为空的队列中&#xff08;若两个都为空&#xff0c;则随便压…

零基础入门进程间通信:task 1(匿名管道与vscode使用)

目录 引言 VSCODE使用 进程间通信正题 基础背景 进程间通信分类 匿名管道 理解匿名管道 代码实现 匿名管道的特性 管道的四种情况 应用场景 引言 在当今的计算机技术领域&#xff0c;操作系统作为计算机系统的核心组件&#xff0c;承担着资源管理、任务调度和进程管…

#渗透测试#SRC漏洞挖掘#Python自动化脚本的编写04之通过面向对象编程学生管理信息系统01

免责声明 本教程仅为合法的教学目的而准备&#xff0c;严禁用于任何形式的违法犯罪活动及其他商业行为&#xff0c;在使用本教程前&#xff0c;您应确保该行为符合当地的法律法规&#xff0c;继续阅读即表示您需自行承担所有操作的后果&#xff0c;如有异议&#xff0c;请立即停…

【销帮帮-注册_登录安全分析报告-试用页面存在安全隐患】

联通支付注册/登录安全分析报告 前言 由于网站注册入口容易被黑客攻击&#xff0c;存在如下安全问题&#xff1a; 暴力破解密码&#xff0c;造成用户信息泄露短信盗刷的安全问题&#xff0c;影响业务及导致用户投诉带来经济损失&#xff0c;尤其是后付费客户&#xff0c;风险巨…

微信小程序——01开发前的准备和开发工具

文章目录 一、开发前的准备1注册小程序账号2安装开发者工具 一、开发前的准备 开发前需要进行以下准备&#xff1a; 1 注册小程序账号2激活邮箱3 信息登记4 登录小程序管理后台5完善小程序信息6绑定开发者 1注册小程序账号 第1步&#xff1a;首先打开“微信公众平台” https:…

文心一言 VS 讯飞星火 VS chatgpt (388)-- 算法导论24.5 8题

八、设 G ( V , E ) G(V,E) G(V,E) 为一个带权重的有向图&#xff0c;且包含一个可以从源结点 s s s 到达的权重为负值的环路。请说明如何构造一个 G G G 的边的松弛操作的无限序列&#xff0c;使得每一步松弛操作都能对某一个最短路径估计值进行更新。如果要写代码&#x…

鸿蒙UI开发——自定义UI绘制帧率

1、概 述 随着设备屏幕的不断演进&#xff0c;当前主流设备采用LTPO屏幕&#xff08;可变刷新率屏幕&#xff09;&#xff0c;此类屏幕支持在多个档位之间切换屏幕帧率。 对于快速变化的内容&#xff0c;如射击游戏&#xff0c;交互动画等&#xff0c;显示帧率越高&#xff0…

计算机毕业设计 | SpringBoot慈善公益平台 爱心互助活动发布管理系统(附源码)

1&#xff0c;项目介绍 爱慈善公益平台&#xff08;love-charity&#xff09;是一个基于 SpringBoot 开发的标准 Java Web 项目。整体页面非常的简约大气&#xff0c;项目的完整度较高&#xff0c;是一个偏向公益论坛的系统。非常适合刚刚接触学习 SpringBoot 的技术小白学习&…

在 AMD GPU 上使用 AI2 的 OLMo 模型进行推理

Inferencing with AI2’s OLMo model on AMD GPU — ROCm Blogs 2024 年 4 月 17 日&#xff0c;作者&#xff1a;Douglas Jia. 在这篇博客中&#xff0c;我们将向您展示如何在 AMD GPU 上使用 AI2 的 OLMo 模型生成文本。 简介 由艾伦人工智能研究所&#xff08;Allen Instit…

工作流初始错误 泛微提交流程提示_泛微协同办公平台E-cology8.0版本后台维护手册(11)–系统参数设置

工作流初始错误 泛微提交流程提示_泛微协同办公平台E-cology8.0版本后台维护手册(11)–系统参数设置...-CSDN博客 工作流初始错误 泛微提交流程提示_泛微OA 工作流WebService接口使用说明 工作流初始错误 泛微提交流程提示_泛微OA 工作流WebService接口使用说明-CSDN博客 工作…

C++数学

前言 C算法与数据结构 打开打包代码的方法兼述单元测试 数论&#xff1a;质数、最大公约数、菲蜀定理 组合数学汇总 计算几何 博弈论 曼哈顿距离与切比雪夫距离 红线是哈曼顿距离&#xff0c;绿线是切比雪夫距离。 二维曼哈顿距离转切比雪夫距离 曼哈顿距离&#xff1a;|…

前深度学习时代-经典的推荐算法

参考自《深度学习推荐系统》—— 王喆&#xff0c;用于学习记录。 1.协同过滤 “协同过滤”就是协同大家的反馈、评价和意见一起对海量的信息进行过滤&#xff0c;从中筛选出目标用户可能感兴趣的信息的推荐过程。 基于用户相似度进行推荐的协同过滤算法 UserCF 用户相似度…

10 Oracle Data Guard:打造高可用性与灾难恢复解决方案,确保业务连续性

文章目录 10 Oracle Data Guard&#xff1a;打造高可用性与灾难恢复解决方案&#xff0c;确保业务连续性一、Data Guard基本概念二、Data Guard技术架构三、配置Oracle Data Guard的步骤3.1 准备主数据库和备用数据库3.2 配置Redo日志传输服务3.3 配置Data Guard Broker3.4 启动…

计算机网络综合题

IP数据报的划分 CRC差错检测 冗余码的计算 因此&#xff0c;余数是1110&#xff0c;传输的数为11010110111110。在传输过程中最后两位变成o&#xff0c;接收端能够发现&#xff0c;因为11010110111110除以10011余数不为0。 子网划分 暴力求解法 &#xff08;定长子网划分大量…

计算机课程管理:Spring Boot与工程认证的协同

2相关技术 2.1 MYSQL数据库 MySQL是一个真正的多用户、多线程SQL数据库服务器。 是基于SQL的客户/服务器模式的关系数据库管理系统&#xff0c;它的有点有有功能强大、使用简单、管理方便、安全可靠性高、运行速度快、多线程、跨平台性、完全网络化、稳定性等&#xff0c;非常…

Java | Leetcode Java题解之第557题反转字符串中的单词III

题目&#xff1a; 题解&#xff1a; class Solution {public String reverseWords(String s) {StringBuffer ret new StringBuffer();int length s.length();int i 0;while (i < length) {int start i;while (i < length && s.charAt(i) ! ) {i;}for (int …

C++ | Leetcode C++题解之第556题下一个更大元素III

题目&#xff1a; 题解&#xff1a; class Solution { public:int nextGreaterElement(int n) {int x n, cnt 1;for (; x > 10 && x / 10 % 10 > x % 10; x / 10) {cnt;}x / 10;if (x 0) {return -1;}int targetDigit x % 10;int x2 n, cnt2 0;for (; x2 …