后端返回了 xlsx 文件流,前端怎么下载处理

当后端返回一个 .xlsx 文件流时,前端可以通过 JavaScript 处理这个文件流并触发浏览器下载。


实现步骤

  1. 发送请求获取文件流
    使用 fetchaxios 等工具向后端发送请求,确保响应类型设置为 blob(二进制数据流)。

  2. 创建 Blob 对象
    将返回的文件流转换为 Blob 对象,这是处理二进制数据的标准方式。

  3. 生成下载链接
    使用 URL.createObjectURL 方法将 Blob 对象转换为一个临时 URL。

  4. 触发下载
    动态创建一个 <a> 标签,设置其 href 属性为生成的临时 URL,并调用 click() 方法触发下载。

  5. 清理资源
    下载完成后,使用 URL.revokeObjectURL 释放生成的临时 URL,避免内存泄漏。


使用 axios 实现

如果你使用的是 axios,可以这样实现:

import axios from 'axios';const downloadXlsx = async () => {try {// 发送请求并获取文件流const response = await axios.get('/api/download-xlsx', {responseType: 'blob', // 确保响应类型为 blobheaders: {'Authorization': 'Bearer your_token_here', // 如果需要携带认证信息},});// 创建 Blob 对象const blob = new Blob([response.data], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' });// 创建临时 URLconst url = window.URL.createObjectURL(blob);// 创建 <a> 标签并触发下载const a = document.createElement('a');a.href = url;a.download = 'example.xlsx'; // 设置下载文件名document.body.appendChild(a); // 将 <a> 添加到 DOM 中(可选)a.click(); // 触发点击事件// 清理资源window.URL.revokeObjectURL(url);a.remove(); // 移除 <a> 标签} catch (error) {console.error('下载文件时发生错误:', error.message || '未知错误');}
};// 调用函数
downloadXlsx();
responseType: 'blob' 的含义
  • responseType 是 Axios 提供的一个配置选项,用于告诉 Axios 如何解析服务器返回的数据。
  • 当设置为 'blob' 时,表示你期望服务器返回的数据是一个二进制大对象(Binary Large Object,简称 Blob)。
Blob 是什么?
  • Blob 是一种数据类型,通常用来表示不可变的、原始数据的类文件对象。
  • 它可以包含文本、图像、音频、视频等二进制数据,或者混合内容。
  • 在前端开发中,Blob 常用于处理文件下载、图片预览、或者将数据保存为文件。
为什么需要 responseType: 'blob'

当从服务器请求文件(如 Excel 文件、PDF 文件、图片等)时,服务器通常会返回二进制数据。如果直接使用默认的 responseType(通常是 'json'),Axios 会尝试将响应数据解析为 JSON 格式,这会导致错误或数据损坏。

通过设置 responseType: 'blob',你可以确保 Axios 正确地将响应数据作为二进制数据处理,而不会尝试将其解析为其他格式(如 JSON 或文本)。

代码的作用
const response = await axios({url: '/api/download-xlsx',method: 'GET',responseType: 'blob', // 指定响应数据为 Blob 类型
});
  1. 发起 GET 请求

    • 向 /api/download-xlsx 发起一个 GET 请求,通常用于下载文件(例如 Excel 文件)。
  2. 指定响应类型

    • 设置 responseType: 'blob',告诉 Axios 将服务器返回的数据解析为 Blob 对象。
  3. 处理响应数据

    • 返回的 response.data 将是一个 Blob 对象,代表下载的文件内容。

使用 fetch 实现

const downloadXlsx = async () => {try {// 发送请求并获取文件流const response = await fetch('/api/download-xlsx', {method: 'GET',headers: {'Authorization': 'Bearer your_token_here', // 如果需要携带认证信息},});// 检查响应是否成功if (!response.ok) {throw new Error(`HTTP error! Status: ${response.status}`);}// 获取 blob 数据const blob = await response.blob();// 创建临时 URLconst url = window.URL.createObjectURL(blob);// 创建 <a> 标签并触发下载const a = document.createElement('a');a.href = url;a.download = 'example.xlsx'; // 设置下载文件名document.body.appendChild(a); // 将 <a> 添加到 DOM 中(可选)a.click(); // 触发点击事件// 清理资源window.URL.revokeObjectURL(url);a.remove(); // 移除 <a> 标签} catch (error) {console.error('下载文件时发生错误:', error.message || '未知错误');}
};// 调用函数
downloadXlsx();
1. 定义异步函数
javascript
深色版本
const downloadXlsx = async () => {
  • async 关键字表示这是一个异步函数。
  • 异步函数允许使用 await 来等待异步操作(如网络请求)完成。

2. 发起 HTTP 请求
const response = await fetch('/api/download-xlsx', {method: 'GET',headers: {'Authorization': 'Bearer your_token_here', // 如果需要携带认证信息},
});
  • 使用 fetch 发起一个 GET 请求到 /api/download-xlsx

  • headers 部分用于设置请求头:

    • 'Authorization' 是一个常见的请求头字段,用于传递用户的身份验证信息(如 JWT Token)。
    • 如果 API 不需要认证,可以省略 headers

3. 检查响应状态
if (!response.ok) {throw new Error(`HTTP error! Status: ${response.status}`);
}
  • response.ok 是一个布尔值,表示 HTTP 响应的状态码是否在 200-299 范围内。
  • 如果响应失败(如 404 或 500 错误),会抛出一个错误,并终止后续代码执行。
  • 抛出的错误会被 catch 块捕获。

4. 获取 Blob 数据
const blob = await response.blob();
  • response.blob()  将响应数据解析为一个 Blob 对象。
  • Blob 是一种二进制数据类型,通常用来表示文件内容。
  • await 确保在继续执行后续代码之前,blob 数据已经被完全加载。

5. 创建临时 URL
const url = window.URL.createObjectURL(blob);
  • window.URL.createObjectURL(blob)  创建一个指向 Blob 的临时 URL。
  • 这个 URL 可以被用作 <a> 标签的 href 属性,从而触发文件下载。

6. 创建 <a> 标签并触发下载
const a = document.createElement('a');
a.href = url;
a.download = 'example.xlsx'; // 设置下载文件名
document.body.appendChild(a); // 将 <a> 添加到 DOM 中(可选)
a.click(); // 触发点击事件
  • 创建 <a> 标签

    • 使用 document.createElement('a') 动态创建一个 <a> 元素。
  • 设置 <a> 标签属性

    • href:设置为前面生成的临时 URL。
    • download:指定下载文件的名称(如 example.xlsx)。
  • 添加到 DOM 并触发点击

    • 将 <a> 标签添加到文档中(虽然不是必须,但某些浏览器可能需要这样做)。
    • 使用 a.click() 模拟用户点击,从而触发文件下载。

7. 清理资源
window.URL.revokeObjectURL(url);
a.remove();
  • 释放临时 URL

    • 使用 window.URL.revokeObjectURL(url) 释放前面创建的临时 URL,避免内存泄漏。
  • 移除 <a> 标签

    • 使用 a.remove() 从 DOM 中移除 <a> 标签,保持页面整洁。

8. 错误处理
} catch (error) {console.error('下载文件时发生错误:', error.message || '未知错误');
}
  • catch 块 用于捕获和处理可能出现的错误。
  • 如果在 try 块中的任何一步发生错误(如网络问题、API 返回错误等),都会进入 catch 块。
  • 使用 console.error 打印错误信息,方便调试。

9. 调用函数
downloadXlsx();
  • 最后调用 downloadXlsx 函数,触发整个文件下载流程。
适用场景
  • 下载动态生成的文件(如 Excel 表格、PDF 文档等)。
  • 需要通过 API 获取文件内容并提供给用户下载的场景。
注意事项
  1. 跨域问题

    • 如果 API 存在跨域限制,需要确保服务器配置了正确的 CORS(跨域资源共享)策略。
  2. 大文件下载

    • 对于非常大的文件,可能需要考虑分块下载或流式处理,以避免内存占用过高。
  3. 浏览器兼容性

    • fetch 和 Blob 在现代浏览器中广泛支持,但在一些老旧浏览器中可能需要使用 XMLHttpRequest 替代。

关键点说明

  1. 设置正确的 MIME 类型

    • .xlsx 文件的 MIME 类型是 application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
    • 如果后端未正确设置 MIME 类型,前端可以通过 Blob 的第二个参数手动指定。
  2. 动态文件名

    • 如果后端在响应头中提供了文件名(例如通过 Content-Disposition),可以通过解析响应头来动态设置文件名。
    • 示例:
      const contentDisposition = response.headers['content-disposition'];
      let fileName = 'example.xlsx';
      if (contentDisposition && contentDisposition.includes('filename=')) {fileName = contentDisposition.split('filename=')[1].split(';')[0];
      }
      
  3. 错误处理

    • 在实际开发中,务必对请求错误进行处理,例如检查 HTTP 状态码是否为 200,或者捕获网络异常。
  4. 兼容性

    • 上述方法适用于现代浏览器(如 Chrome、Firefox、Edge、Safari)。如果需要支持旧版浏览器,可能需要引入 FileSaver.js 库。

使用 FileSaver.js 简化操作

如果你希望简化文件下载逻辑,可以使用第三方库 file-saver。安装后,只需几行代码即可完成下载。

安装
npm install file-saver
使用示例
import { saveAs } from 'file-saver';
import axios from 'axios';const downloadXlsx = async () => {try {const response = await axios({url: '/api/download-xlsx',method: 'GET',responseType: 'blob',});// 使用 FileSaver.js 保存文件saveAs(response.data, 'example.xlsx');} catch (error) {console.error('下载失败:', error);}
};// 调用函数
downloadXlsx();

总结

  • 核心步骤:获取文件流 -> 转换为 Blob -> 创建临时 URL -> 触发下载 -> 清理资源。
  • 推荐工具fetchaxios 可以轻松获取文件流,FileSaver.js 可以进一步简化代码。
  • 注意事项:确保后端返回的文件流格式正确,前端设置合适的 MIME 类型和文件名。

axios 处理

try {const response = await axios({url: '/api/download-xlsx',method: 'GET',responseType: 'blob', // 一定要注意请求时加此方法});getExportListApi(exportCarryData).then((res) => {// 创建一个a标签const link = document.createElement('a');const url = window.URL.create0bjectURL(new Blob([res.data])); link.href = url;link.setAttribute('download', exportfile);document.body.appendChild(link); link.click();// 销毁a标签document.body.removeChild(link); window.URL.revoke0bjectURL(url);message.success('导出成功!');}); 

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

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

相关文章

HTML5拖拽功能教程

HTML5拖拽功能教程 简介 HTML5引入了原生拖放(Drag and Drop)API&#xff0c;使开发者能够轻松实现网页中的拖拽功能&#xff0c;无需依赖第三方库。拖拽功能可以大大提升用户体验&#xff0c;适用于文件上传、列表排序、看板系统等多种交互场景。本教程将带您全面了解HTML拖…

VUE3 路由配置

1.下载 VueRouter 模块 在命令行中输入 yarn add vue-router 2.导⼊相关函数 在自己创建的router/index.js 文件中 import { createRouter, createWebHashHistory } from vue-router 3.创建路由实例 在自己创建的router/index.js 文件中 const theFirstRouter ()>{return…

历史序列影像 Esri的World Imagery Wayback简介

Esri的World Imagery Wayback是一个专注于提供历史卫星影像的在线平台&#xff0c;由全球领先的地理信息系统&#xff08;GIS&#xff09;技术提供商Esri开发。该平台整合了多源卫星影像数据&#xff0c;允许用户回溯特定区域在不同时间点的影像变化&#xff0c;支持时间序列分…

golang结构体与指针类型

结构体与指针类型 指针类型字段 具名字段 举例 package struct_knowledgeimport "fmt"//结构体字段为指针类型 func StructWithPoint(){type Student struct{name *string}var lisa Studentfmt.Printf("赋值前,Student的实例的值%#v\n",lisa)//错误的赋…

NetMizer-日志管理系统-远程命令执行漏洞挖掘

漏洞描述&#xff1a;NetMizer 日志管理系统 cmd.php中存在远程命令执行漏洞&#xff0c;攻击者通过传入 cmd参数即可命令执行 1.fofa搜素语句 title"NetMizer 日志管理系统" 2.漏洞验证 网站页面 验证POC /data/manage/cmd.php?cmdid

Contactile三轴触觉传感器:多维力感赋能机器人抓取

在非结构化环境中&#xff0c;机器人对物体的精准抓取与操作始终面临巨大挑战。传统传感器因无法全面感知触觉参数&#xff08;如三维力、位移、摩擦&#xff09;&#xff0c;难以适应复杂多变的场景。Contactile推出的三轴触觉力传感器&#xff0c;通过仿生设计与创新光学技术…

OpenCV三维解算常用方法C++

如果标定过程是通过OpenCV张正友标定法实现的&#xff0c;得到的内参外参保存在.txt文件中是这样的形式&#xff1a; ① 内参intrinsics.txt&#xff1a; ② 外参extrinsics.txt&#xff1a; 那么可以通过如下方法读取.txt文件获取左右相机内外参&#xff0c;主要包括三维解算…

栈和队列相关知识题目

栈的底层原理 栈&#xff08;Stack&#xff09;是一种后进先出&#xff08;LIFO&#xff09;​的线性数据结构&#xff0c;所有操作&#xff08;如插入、删除&#xff09;仅在栈顶进行。它的底层实现可以是数组或链表&#xff0c;具体取决于编程语言和应用场景。 1.基于数组实…

【实战案例】永洪vividime:精准赋能零售行业,实现数据洞察与业务增长

在零售食品行业变革加速、市场竞争白热化的背景下&#xff0c;XX集团作为休闲食品领域头部企业&#xff0c;面临消费趋势变化、宏观经济承压及业绩增长乏力的多重挑战。为破解增长困境&#xff0c;集团将“收入增长金额”确立为核心战略指标&#xff08;北极星指标&#xff09;…

一些题目记录

别人面经题目记录 https://zhuanlan.zhihu.com/p/32626732052 实现 NMS&#xff0c;七八次&#xff0c;很高频&#xff1b; 实现 MultiHeadSelfAttention&#xff0c;大概 三四次&#xff1b; 用 Numpy 或者 List 实现MLP 的前向和反向&#xff0c;4次&#xff1b; Leetcode …

面试题分享-多线程顺序打印奇偶数

目录 1.题目详情 2.解题思路 2.1.分析题目 2.2.解析思路 3.代码实现 4.运行结果 1.题目详情 昨天刷抖音&#xff0c;遇到一个面试题&#xff0c;描述如下&#xff1a; 请使用两个线程&#xff0c;分别顺序交替打印奇数和偶数&#xff0c;直到10为止。例如有两个线程&#…

模型 杜根定律

系列文章分享模型&#xff0c;了解更多&#x1f449; 模型_思维模型目录。信心>能力、行动导向、未来时态。 1 杜根定律的应用 1.1 公共政策博弈——底特律市长杜根的保险改革攻坚战 核心挑战&#xff1a;底特律市长Mike Duggan面临汽车保险费率畸高导致居民陷入贫困循环的…

关于在vscode中的Linux 0.11 应用程序项目的生成和运行

首先我们需要需要查看镜像文件 查看软盘镜像文件 floppyb.img 中的内容 在 VSCode 的“Terminal”菜单中选择“Run Build Task...”&#xff0c;会在 VSCode 的顶部中间位置弹出一个 可以执行的 Task 列表&#xff0c;选择其中的“打开 floppyb.img”后会使用 Floppy Editor …

使用CSS3实现炫酷的3D视差滚动效果

使用CSS3实现炫酷的3D视差滚动效果 这里写目录标题 使用CSS3实现炫酷的3D视差滚动效果项目概述核心技术实现1. 3D空间的创建2. 视差层级设置3. 动画效果实现流星动画月亮发光效果 技术难点与解决方案1. 层级重叠问题2. 性能优化3. 响应式适配 开发心得总结 项目概述 在这个项目…

作业12 (2023-05-15 指针概念)

第1题/共11题【单选题】 关于指针的概念,错误的是:( ) A.指针变量是用来存放地址的变量 B.指针变量中存的有效地址可以唯一指向内存中的一块区域 C.野指针也可以正常使用 D.局部指针变量不初始化就是野指针 回答正确 答案解析: A:正确,指针变量中存储的是一个地址,指…

【ESP32S3】esp32获取串口数据并通过http上传到前端

通过前面的学习&#xff08;前面没发过&#xff0c;因为其实就是跑它的demo&#xff09;了解到串口配置以及开启线程实现功能的工作流程&#xff0c;与此同时还有esp32作为STA节点&#xff0c;将数据通过http发送到服务器。 将这两者联合 其实是可以得到一个&#xff1a;esp32获…

《鸿蒙携手AI:解锁智慧出行底层逻辑》

在科技飞速发展的当下&#xff0c;智慧出行成为人们对未来交通的美好期许&#xff0c;而鸿蒙系统与人工智能的深度融合&#xff0c;正为这一愿景的实现提供强大助力。从技术原理角度深入剖析&#xff0c;鸿蒙系统究竟如何支撑人工智能在智慧出行场景中的应用呢&#xff1f;这背…

MyBatis-Plus缓存机制深度解析与SpringBoot整合实战

一、MyBatis-Plus缓存机制全景解析 MyBatis-Plus在MyBatis原生缓存基础上进行了深度增强,形成了多层次的缓存体系: 1. 缓存层级架构 应用层 ├── MP扩展缓存(多租户/逻辑删除) ├── 二级缓存(Mapper级别,跨Session共享) └── 一级缓存(SqlSession级别,默认开…

Day38 | 1365. 有多少小于当前数字的数字、941. 有效的山脉数组、1207. 独一无二的出现次数、283. 移动零、189. 轮转数组

1365. 有多少小于当前数字的数字 题目链接&#xff1a;1365. 有多少小、于当前数字的数字 - 力扣&#xff08;LeetCode&#xff09; 题目难度&#xff1a;简单 代码&#xff1a; class Solution {public int[] smallerNumbersThanCurrent(int[] nums) {Map<Integer,Inte…

数据人的进阶之路:四年数仓实践与成长思考

前言 在数据仓库开发的过程中&#xff0c;常常会遇到很多值得思考的问题&#xff0c;它们不仅关乎技术的深度&#xff0c;也涉及业务理解、个人的成长&#xff0c;甚至是数据行业未来的价值。回顾过去的经历&#xff0c;有很多问题反复出现&#xff0c;甚至成为绕不开的课题&am…