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

我是前端max 2024-07-17 09:03:02 阅读 97

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

1.设置responseType为arraybuffer

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

<code>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);code>

ElMessage.error('下载文件失败');

}

}



声明

本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。