【Vue】使用Axios请求下载后端返回的文件流,并能够提示后端报错信息

【需求】使用Axios请求下载后端返回的文件流,下载失败时提示信息不写死,按照后端返回的信息进行提示。

一、需求分析

看到这个需求的时候,有人可能会很疑惑,这不是直接就能获取到吗,直接message.error()弹框就完事了,有什么问题。

我们先来模拟一下,点击按钮下载文件,请求后端接口,后端返回文件流,前端通常会设置响应类型为blob, responseType: 'blob',如:

javascript 复制代码
// 下载文件
export function HandleDownLoadFile(params) {
    return request({
        url: '/xxxx/download',
        method: 'get',
        params,
        responseType: 'blob'
    });
}

我们打印响应数据看看是什么,可以发现res.data是一个Blob格式的数据,和正常的格式已经不同了,后端返回的message也获取不到了。

  • 文件流返回示例

  • 正常数据返回示例

二、解决问题

首先我我们先看下请求成功和失败的返回结果有无不同。

请求下载一个文件,请求成功时返回的是一个文件流,type是对应文件类型,例如:text/xml,正常导出文件;而请求失败的时候返回的是json ,type为application/json,不会处理错误信息,而是直接导出包含错误信息的文件。

但是无论成功还是失败,返回的结果都是blob格式的文件流。

因此可以通过返回的blob数据type类型进行区分,如果type是文件类型,导出文件,如果type是json则把blob数据转为string,处理错误信息。

在axios响应拦截器中,对二进制数据单独处理,如果type为application/json说明下载失败,那么弹出对应错误信息,然后返回Null,否则下载成功,正常返回res.data。

javascript 复制代码
// 响应拦截器
service.interceptors.response.use(res => {
    ...
    // 二进制数据处理
    if (res.request.responseType === 'blob' || res.request.responseType === 'arraybuffer') {
        if (res.data.type === 'application/json') {
            const reader = new FileReader();
            reader.onload = () => {
            // TODO 错误处理
                this.$message.error(
                    `Error: ${JSON.parse(reader.result).message}!`
                );
            };
            reader.readAsText(res.data);
            return null;
        } else {
            return res.data;
        }
    }
    ...
}

然后在通用下载函数中,首先进行判断,如果file存在,才开始下载操作。

javascript 复制代码
export const DownloadFile = (file, fileName = 'file.xlsx') => {
    if (file) {
        const blob = new Blob([file]);
        // 获取heads中的filename文件名
        const downloadElement = document.createElement('a');
        // 创建下载的链接
        const href = window.URL.createObjectURL(blob);
        downloadElement.href = href;
        // 下载后文件名
        downloadElement.download = fileName;
        document.body.appendChild(downloadElement);
        // 点击下载
        downloadElement.click();
        // 下载完成移除元素
        document.body.removeChild(downloadElement);
        // 释放掉blob对象
        window.URL.revokeObjectURL(href);
    }
};

关键在于借助FileReader对象 实现,FileReader.readAsText(data)开始读取指定的Blob中的内容。一旦完成,result属性中将包含一个字符串以表示所读取的文件内容。

读取操作完成时触发FileReader.onload(),在这里通过reader.result拿到读取的文件内容(即后端返回值),然后对其json序列化,即可拿到后端返回的message,然后进行相应的展示即可。

即下面这段代码:

javascript 复制代码
if (res.data.type === 'application/json') {
    const reader = new FileReader();
    reader.readAsText(res.data);
    reader.onload = () => {
    // TODO 错误处理
        this.$message.error(
            `Error: ${JSON.parse(reader.result).message}!`
        );
    };
    return null;
}

至此,问题解决。

总结

主要在于Blob格式返回错误怎么拿到的问题,通过type判断是否请求成功,然后借助FileReader对象读取blob格式文件内容,拿到需要的结果。

参考文章:https://blog.csdn.net/qq_27626333/article/details/103562749

相关推荐
崔庆才丨静觅4 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby60615 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了5 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅5 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅6 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅6 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment6 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅6 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊6 小时前
jwt介绍
前端
爱敲代码的小鱼6 小时前
AJAX(异步交互的技术来实现从服务端中获取数据):
前端·javascript·ajax