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

前端Ajax请求从后端获取二进制文件并下载

大家都知道前端的下载除了最简单的a标签href,还有时候需要验证token,此时后台会给一个返回二进制的下载接口。如果你用ajax普通的get,post请求,接口会返回乱码。那么本文就带你封装一个处理二进制下载的方法。

1.设置responseType为arraybuffer

这是正确获取二进制的关键,否则会被当成json文本来解析。

const response = await axios({method,url,data,responseType: 'arraybuffer',headers,
});

2.判断是否下载成功 

只有下载成功的时候返回的才是arraybuffer,否则是包含错误信息的json,因此在这里我们通过响应头的contentType来判断。

if (contentType?.includes('application/json')) {// 响应的是json则提示错误信息const res = JSON.parse(new TextDecoder('utf-8').decode(new Uint8Array(response.data)));if (res.code !== 200) {ElMessage({message: res.msg,type: 'error',duration: 5 * 1000});return;}
}

3.获取blobUrl 

// blobType可以是空对象{},或指定的excel等MIME类型
const data = new Blob([response.data], blobType); 
const src = window.URL.createObjectURL(data);

4.下载文件 

传入获取到的blobUrl,可以用第三方库file-saver下载,也可以用a标签的download属性。file-saver对各浏览器做了blob等兼容处理。

import { saveAs } from 'file-saver';// 第一种 使用第三方库 file-saver
saveAs(src, filename); // 第二种 a标签
function aTagDownload(src, filename) {const link = document.createElement('a');link.href = src;link.setAttribute('download', filename);document.body.appendChild(link);link.click();document.body.removeChild(link);window.URL.revokeObjectURL(src);
}

完整代码

/*** 下载二进制文件* @param {string} method 必填 请求方式* @param {string} url 必填 下载 url* @param {object} [data={}] post 请求的 data* @param {object} [headers={}] 请求的 headers* @param {string} [filename=下载.zip] 保存的文件名,默认为下载.zip* @param {boolean} [isDownload=true] 是否直接下载,默认为 true* @param {object} [blobType={}] 指定 blob MIME 类型,默认为{}* @returns {string} blobUrl*/
export async function getBufferFile(method,url,data = {},headers = {},filename = '下载.zip',isDownload = true,blobType = {},
) {headers = {...headers,Authorization: localStorage.getItem('token'),};ElMessage.success('已开始下载');try {const response = await axios({method,url,data,responseType: 'arraybuffer',headers,});const contentType = response.headers['content-type'];// 根据响应头的contentType判断是否下载成功if (contentType?.includes('application/json')) {// 响应的是json则提示错误信息const res = JSON.parse(new TextDecoder('utf-8').decode(new Uint8Array(response.data)));if (res.code !== 200) {ElMessage({message: res.msg,type: 'error',duration: 5 * 1000});return;}} else {const data = new Blob([response.data], blobType);const src = window.URL.createObjectURL(data);// 从响应头获取文件名if (response.headers['content-disposition']) {filename = decodeURI(response.headers['content-disposition'].split('filename=')[1]);}if (isDownload) {saveAs(src, filename); // 使用第三方库 file-saver}return src;}} catch (error) {console.error('下载文件失败:', error);ElMessage.error('下载文件失败');}
}

相关文章:

  • STM32学习笔记(9_2)- USART串口外设
  • qt学习第三天,qt设计师的第一个简单案例
  • JVM(一)——内存结构
  • 实验十 枚举问题(过程模拟)
  • 正则表达式 vs. 字符串处理:解析优势与劣势
  • [linux][调度] 内核抢占入门 —— 高优先级线程被唤醒时会立即抢占当前线程吗 ?
  • PCM /G711音频播放器 :Audacity
  • js 分割号查找内容
  • Unity 镜头动画
  • Rust 实战练习 - 8. 内存,ASM,外挂 【重磅】
  • HJ73 计算日期到天数转换
  • 为什么要使用注意力机制?
  • ip 协议
  • gateway 分发时若两个服务的路由地址一样,怎么指定访问想要的服务下的地址
  • Mysql-实战数据备份与恢复
  • ----------
  • ES6指北【2】—— 箭头函数
  • 【391天】每日项目总结系列128(2018.03.03)
  • 〔开发系列〕一次关于小程序开发的深度总结
  • css布局,左右固定中间自适应实现
  • es6
  • HashMap剖析之内部结构
  • HomeBrew常规使用教程
  • input实现文字超出省略号功能
  • JavaScript 一些 DOM 的知识点
  • Netty 4.1 源代码学习:线程模型
  • Spark RDD学习: aggregate函数
  • UEditor初始化失败(实例已存在,但视图未渲染出来,单页化)
  • 阿里研究院入选中国企业智库系统影响力榜
  • 测试如何在敏捷团队中工作?
  • 对话:中国为什么有前途/ 写给中国的经济学
  • 前嗅ForeSpider中数据浏览界面介绍
  • 如何学习JavaEE,项目又该如何做?
  • 跳前端坑前,先看看这个!!
  • 微信公众号开发小记——5.python微信红包
  • 云大使推广中的常见热门问题
  • 阿里云ACE认证学习知识点梳理
  • 阿里云API、SDK和CLI应用实践方案
  • ​TypeScript都不会用,也敢说会前端?
  • $.each()与$(selector).each()
  • (17)Hive ——MR任务的map与reduce个数由什么决定?
  • (附源码)spring boot公选课在线选课系统 毕业设计 142011
  • (附源码)计算机毕业设计高校学生选课系统
  • (经验分享)作为一名普通本科计算机专业学生,我大学四年到底走了多少弯路
  • (学习日记)2024.03.12:UCOSIII第十四节:时基列表
  • (一)SpringBoot3---尚硅谷总结
  • (转)LINQ之路
  • ***原理与防范
  • .CSS-hover 的解释
  • .java 9 找不到符号_java找不到符号
  • .net oracle 连接超时_Mysql连接数据库异常汇总【必收藏】
  • .NET/C# 项目如何优雅地设置条件编译符号?
  • /dev下添加设备节点的方法步骤(通过device_create)
  • /usr/local/nginx/logs/nginx.pid failed (2: No such file or directory)
  • @Service注解让spring找到你的Service bean