当前位置: 首页 > news >正文

下载文件--后端返回文件数据,前端怎么下载呢

问题:有个功能是将tabel数据导出,并且后端写了个接口,这个接口返回你要下载的excel文件数据了。前端请求接口就行,然后下载下来,但前端该怎么操作(发起请求呢)

/*** 导出文件* @param {string} url - 导出文件的 API 地址* @param {Object} data - 导出文件的请求参数*/
export function exportFile(url, data) {const reqData = {...data,...initReqData(),//一些必要固定参数};axios({url,baseURL: import.meta.env.VITE_BASE_URL,data: reqData,responseType: 'blob',//设置为'blob',表示期望服务器响应的数据类型为二进制大对象(Blob),这对于下载文件特别有用。method: 'post',}).then(res => {if (res.data.type === 'application/json') {throw res;}const link = document.createElement('a');const blob = new Blob([res.data], { type: 'application/vnd.ms-excel' });link.style.display = 'none';link.href = URL.createObjectURL(blob);const contentDisposition = res.headers['content-disposition'];let needle = 'filename*=utf-8\'\'';let index = contentDisposition.indexOf(needle);if (index < 0) {needle = 'filename=';index = contentDisposition.indexOf(needle);}let fileName = contentDisposition.substring(index + needle.length);fileName = decodeURI(fileName);link.setAttribute('download', `${fileName}`);document.body.appendChild(link);link.click();document.body.removeChild(link);message.success('导出成功');}).catch(error => {try {const reader = new FileReader();reader.readAsText(error.data, 'utf-8');reader.onload = () => {const errData = JSON.parse(reader.result);message.error(errData.msg);};} catch (e) {message.error('导出错误,请联系管理员');}});
}

请求发送

  1. 请求配置
    • url:请求的URL,这里假设它已经在外部定义好了。
    • baseURL:通过import.meta.env.VITE_BASE_URL获取基础URL,这是Vite环境变量的一种用法,用于在开发、测试和生产环境中配置不同的基础URL。
    • datareqData,这是要发送到服务器的数据。
    • responseType:设置为'blob',表示期望服务器响应的数据类型为二进制大对象(Blob),这对于下载文件特别有用。
    • method'post',表示这是一个POST请求。
  2. 请求发送:使用axios发送配置好的请求。

响应处理

  1. 检查响应类型
    • 首先,检查响应的Content-Type。如果响应类型是'application/json',则抛出异常,因为预期是下载文件而不是接收JSON数据。
  2. 处理文件下载
    • 创建一个Blob对象,将响应数据(res.data)作为其内容,并设置MIME类型为'application/vnd.ms-excel',这是Excel文件的MIME类型。
    • 创建一个隐藏的<a>标签,设置其href属性为Blob对象的URL(通过URL.createObjectURL(blob)生成),并设置download属性为文件名(从Content-Disposition响应头中提取)。
    • <a>标签添加到文档中,模拟点击以触发下载,然后立即从文档中移除该标签。
    • 显示“导出成功”的消息。

错误处理

  1. 捕获异常
    • 如果在下载过程中发生错误(如服务器返回JSON格式的错误信息),则尝试读取错误响应的data部分作为文本。
    • 使用FileReader读取响应数据,并将其解析为JSON对象。
    • 如果解析成功,则显示错误消息(errData.msg)。
    • 如果在读取或解析过程中发生任何异常,则显示一般的错误消息“导出错误,请联系管理员”。

部分代码解析:

主要用于从HTTP响应的Content-Disposition头部中提取文件名,并设置给一个<a>标签的download属性,以便在点击该链接时以下载的形式保存文件。下面是对这几部分代码的详细讲解:

1. 提取Content-Disposition头部

const contentDisposition = res.headers['content-disposition'];

这行代码从HTTP响应的头部信息中获取Content-Disposition字段的值。这个字段通常用于指示响应的内容应该如何显示,对于文件下载来说,它还可能包含文件名。

2. 处理文件名编码

HTTP标准允许Content-Disposition中的文件名使用不同的编码方式,特别是当文件名包含非ASCII字符时。这里,代码首先尝试找到使用RFC 5987编码的文件名(即filename*=utf-8''这种格式),如果没有找到(indexOf返回-1),则回退到较旧的filename=格式。

let needle = 'filename*=utf-8\'\'';
let index = contentDisposition.indexOf(needle);
if (index < 0) {
needle = 'filename=';
index = contentDisposition.indexOf(needle);
}
  • needle变量用于存储要搜索的字符串(即文件名前的标识符)。
  • indexOf方法用于查找needlecontentDisposition字符串中的位置。
  • 如果找不到使用RFC 5987编码的文件名(index < 0),则更改needlefilename=并再次搜索。

3. 提取文件名

let fileName = contentDisposition.substring(index + needle.length);

一旦找到了文件名的起始位置(index + needle.length),就使用substring方法从该位置开始提取剩余的字符串作为文件名。这包括了文件名本身以及可能存在的任何引号(如果使用的是filename=格式,则文件名可能会被引号包围)。

4. 解码文件名

fileName = decodeURI(fileName);

由于文件名可能是经过URI编码的(特别是当包含特殊字符或空格时),因此使用decodeURI函数对其进行解码,以确保文件名在下载时正确显示。

5. 设置下载链接

link.setAttribute('download', `${fileName}`);
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
  • 使用setAttribute方法将解码后的文件名设置为<a>标签的download属性。这告诉浏览器,当用户点击该链接时,应以下载的形式保存内容,并使用指定的文件名。
  • <a>标签添加到文档的body中,以便可以触发其点击事件。
  • 调用click方法模拟点击事件,触发下载。
  • 下载完成后,立即从文档中移除<a>标签,以清理DOM。

这样,当用户通过这段代码触发下载时,浏览器会根据Content-Disposition头部中的信息(特别是文件名)来保存文件。

 

相关文章:

下载文件--后端返回文件数据,前端怎么下载呢

问题&#xff1a;有个功能是将tabel数据导出&#xff0c;并且后端写了个接口&#xff0c;这个接口返回你要下载的excel文件数据了。前端请求接口就行&#xff0c;然后下载下来&#xff0c;但前端该怎么操作&#xff08;发起请求呢&#xff09; /*** 导出文件* param {string} …...

CSS方向选择的艺术:深入探索:horizontal和:vertical伪类

CSS&#xff08;层叠样式表&#xff09;是构建网页视觉表现的核心工具。随着CSS规范的不断更新&#xff0c;我们拥有了更多的选择器来精确控制网页元素的样式。其中&#xff0c;:horizontal和:vertical伪类是CSS Level 4中引入的两个实验性选择器&#xff0c;它们允许开发者根据…...

探索PHP的心脏:流行CMS系统全解析

标题&#xff1a;探索PHP的心脏&#xff1a;流行CMS系统全解析 在数字化时代&#xff0c;内容管理系统&#xff08;CMS&#xff09;扮演着构建和维护网站的核心角色。PHP作为一种广泛使用的服务器端脚本语言&#xff0c;其强大的功能和灵活性使其成为开发CMS的首选。本文将详细…...

图片展示控件QGraphicsView、QGraphicsScene、QGraphicsItem的使用Demo

简介 /* * 图片展示控件 * Graphics View Framework的使用Demo * QGraphicsView、QGraphicsScene、QGraphicsItem的使用Demo * 支持图片的旋转与缩放&#xff0c;自动缩放至接触边框 */ 效果展示 坐标系示意图 Graphics View Framework的使用需要特别注意QGraphicsView、…...

C++仿C#实现事件处理

测试 #include "beacon/beacon.hpp" #include <cstdio> #include <thread>class mouseEvent : public beacon::args { public:mouseEvent(int x, int y) : x(x), y(y) {}int x, y; };class object : public beacon::sender { public:};class mouseHandl…...

SpringBoot-04--整合登录注册动态验证码

文章目录 效果展示1.导入maven坐标2.编写代码生成一个验证码图片3.前端如何拿到验证码4. 后端生成验证码5前端代码 效果展示 效果&#xff0c;每次进入页面展现出来不同的验证码。 技术 使用别人已经写好的验证码生成器&#xff0c;生成图片&#xff0c;转为Base64编码&#x…...

Qt如何打包桌面应用程序

Qt提供了一种便捷的方式来打包桌面应用程序&#xff0c;使其能够在不同操作系统上运行。以下是一些常用的打包工具和步骤&#xff1a; 1. **使用Qt Installer Framework**&#xff1a;Qt提供了一个名为Qt Installer Framework的工具&#xff0c;可以用来创建跨平台的安装程序。…...

AI作画提示词工程:技巧与最佳实践

在AI作画中&#xff0c;提示词工程&#xff08;Prompt Engineering&#xff09;是生成高质量图像的关键一步。以Midjourney为例&#xff0c;通过巧妙设计提示词&#xff0c;AI能够生成更符合预期的图像。本教程将分享如何有效利用提示词&#xff0c;掌握提示词的技巧与最佳实践…...

Ugandan Knuckles

目录 一、题目 二、思路 三、payload 四、思考与总结 一、题目 <!-- Challenge --> <div id"uganda"></div> <script>let wey (new URL(location).searchParams.get(wey) || "do you know da wey?");wey wey.replace(/[<…...

MVI、MVVM、MVP的对比

MVI 特点&#xff1a; 单向数据流&#xff1a;MVI采用单向数据流&#xff0c;从Model到View的数据流动&#xff0c;保证了数据流的可控性和可预测性。响应式编程&#xff1a;通过使用协程与RxJava等响应式编程库&#xff0c;简化了数据流的管理和处理。不可变性&#xff1a;MV…...

基于 Flutter 从零开发一款产品(一)—— 跨端开发技术介绍

前言 相信很多开发者在学习技术的过程中&#xff0c;常常会陷入一种误区当中&#xff0c;就是学了很多技术理论知识&#xff0c;但是仍做不出什么产品出来&#xff0c;往往学了很多干货&#xff0c;但是并无实际的用处。其实&#xff0c;不论是做什么&#xff0c;我们都需要从…...

React + Vite项目别名配置

Node版本&#xff1a;v20.16.0Vite版本&#xff1a;5.4.1 安装 types/node 依赖包 pnpm i types/node -D pnpm ls types/node配置 vite.config.js 文件: resolve: {alias: {"": join(__dirname, "./src/"),}, },使用配置好的别名 &#xff1a; 由上图我们…...

FFmpeg编译与配置 - Linux环境

Linux环境配置 环境&#xff1a;Ubuntu 22.04 step1. 首先下载安装依赖环境 更新软件源 sudo apt update下载依赖软件 sudo apt install \ autoconf \ automake \ build-essential \ cmake \ git-core \ libass-dev \ libfreetype6-dev \ libgnutls28-dev \ libsdl2-dev \…...

MyBatis-Plus 提供的一个通用服务层实现类

一、代码示例 Service public class CarriageServiceImpl extends ServiceImpl<CarriageMapper, CarriageEntity> implements CarriageService{Overridepublic List<CarriageDTO> findAll() {return List.of();} } 在这段代码中&#xff0c;CarriageServiceImpl …...

41-设计规则:线宽规则

1.设置电源线规则和信号线规则 2.设置信号线规则 3.设置电源线规则 如果未生效&#xff1a; ① 提升优先级即可。 ②查看使能选项有没有勾选...

使用MicroApp重构旧项目

前言 随着技术的飞速发展&#xff0c;我们公司内部一个基于“上古神器” jQuery PHP 构建的十年历史老项目已显力不从心&#xff0c;技术非常老旧且维护成本高昂&#xff0c;其实已经无数次想要重构&#xff0c;但是苦于历史遗留原因以及业务的稳定性而一直难以下手&#xff0…...

【Golang】go mod的使用

【1】GO111MODULE有三个值&#xff1a;off, on, auto off&#xff1a;go命令行将不会支持module功能&#xff0c;将会使用旧版本那种通过vendor目录或者GOPATH来查找依赖包的方式。 on&#xff1a;go命令行会使用modules功能&#xff0c;而不…...

Linux内核之网络套接字

文章目录 前言一、TCP4层模型和OSI7层模型OSI 7层模型TCP/IP 4层模型比较 二、套接字概念三、sockaddr_in和sockaddr结构体sockaddr_insockaddr区别 四、协议中的数据划分数据划分和首部添加流程数据接收与解析流程流程图 前言 一、TCP4层模型和OSI7层模型 OSI 7层模型 物理…...

SpringBoot事务-调度-缓存

一.Spring Boot中的事务管理 设置事务 Transactional(isolation Isolation.DEFAULT) Transactional(propagation Propagation.REQUIRED) 开启事务 EnableTransactionManagement 1. 开启事务管理 要开启 Spring 的事务管理&#xff0c;你需要在你的 Spring Boot 应用中添加 …...

社交媒体分析:如何利用Facebook的数据提升业务决

在数字化时代&#xff0c;社交媒体已经成为企业战略中不可或缺的一部分。Facebook&#xff0c;作为全球最大的社交平台之一&#xff0c;提供了丰富的数据资源&#xff0c;这些数据不仅能够帮助企业了解市场趋势&#xff0c;还能提升业务决策的精准度。本文将探讨如何有效利用Fa…...

IDEA运行Tomcat出现乱码问题解决汇总

最近正值期末周&#xff0c;有很多同学在写期末Java web作业时&#xff0c;运行tomcat出现乱码问题&#xff0c;经过多次解决与研究&#xff0c;我做了如下整理&#xff1a; 原因&#xff1a; IDEA本身编码与tomcat的编码与Windows编码不同导致&#xff0c;Windows 系统控制台…...

使用docker在3台服务器上搭建基于redis 6.x的一主两从三台均是哨兵模式

一、环境及版本说明 如果服务器已经安装了docker,则忽略此步骤,如果没有安装,则可以按照一下方式安装: 1. 在线安装(有互联网环境): 请看我这篇文章 传送阵>> 点我查看 2. 离线安装(内网环境):请看我这篇文章 传送阵>> 点我查看 说明&#xff1a;假设每台服务器已…...

idea大量爆红问题解决

问题描述 在学习和工作中&#xff0c;idea是程序员不可缺少的一个工具&#xff0c;但是突然在有些时候就会出现大量爆红的问题&#xff0c;发现无法跳转&#xff0c;无论是关机重启或者是替换root都无法解决 就是如上所展示的问题&#xff0c;但是程序依然可以启动。 问题解决…...

Redis相关知识总结(缓存雪崩,缓存穿透,缓存击穿,Redis实现分布式锁,如何保持数据库和缓存一致)

文章目录 1.什么是Redis&#xff1f;2.为什么要使用redis作为mysql的缓存&#xff1f;3.什么是缓存雪崩、缓存穿透、缓存击穿&#xff1f;3.1缓存雪崩3.1.1 大量缓存同时过期3.1.2 Redis宕机 3.2 缓存击穿3.3 缓存穿透3.4 总结 4. 数据库和缓存如何保持一致性5. Redis实现分布式…...

UE5 学习系列(三)创建和移动物体

这篇博客是该系列的第三篇&#xff0c;是在之前两篇博客的基础上展开&#xff0c;主要介绍如何在操作界面中创建和拖动物体&#xff0c;这篇博客跟随的视频链接如下&#xff1a; B 站视频&#xff1a;s03-创建和移动物体 如果你不打算开之前的博客并且对UE5 比较熟的话按照以…...

智能在线客服平台:数字化时代企业连接用户的 AI 中枢

随着互联网技术的飞速发展&#xff0c;消费者期望能够随时随地与企业进行交流。在线客服平台作为连接企业与客户的重要桥梁&#xff0c;不仅优化了客户体验&#xff0c;还提升了企业的服务效率和市场竞争力。本文将探讨在线客服平台的重要性、技术进展、实际应用&#xff0c;并…...

新能源汽车智慧充电桩管理方案:新能源充电桩散热问题及消防安全监管方案

随着新能源汽车的快速普及&#xff0c;充电桩作为核心配套设施&#xff0c;其安全性与可靠性备受关注。然而&#xff0c;在高温、高负荷运行环境下&#xff0c;充电桩的散热问题与消防安全隐患日益凸显&#xff0c;成为制约行业发展的关键瓶颈。 如何通过智慧化管理手段优化散…...

PL0语法,分析器实现!

简介 PL/0 是一种简单的编程语言,通常用于教学编译原理。它的语法结构清晰,功能包括常量定义、变量声明、过程(子程序)定义以及基本的控制结构(如条件语句和循环语句)。 PL/0 语法规范 PL/0 是一种教学用的小型编程语言,由 Niklaus Wirth 设计,用于展示编译原理的核…...

汇编常见指令

汇编常见指令 一、数据传送指令 指令功能示例说明MOV数据传送MOV EAX, 10将立即数 10 送入 EAXMOV [EBX], EAX将 EAX 值存入 EBX 指向的内存LEA加载有效地址LEA EAX, [EBX4]将 EBX4 的地址存入 EAX&#xff08;不访问内存&#xff09;XCHG交换数据XCHG EAX, EBX交换 EAX 和 EB…...

Mac下Android Studio扫描根目录卡死问题记录

环境信息 操作系统: macOS 15.5 (Apple M2芯片)Android Studio版本: Meerkat Feature Drop | 2024.3.2 Patch 1 (Build #AI-243.26053.27.2432.13536105, 2025年5月22日构建) 问题现象 在项目开发过程中&#xff0c;提示一个依赖外部头文件的cpp源文件需要同步&#xff0c;点…...