前言
碰到了一个前端的小问题,django后端提供了一个下载文件的接口,前端页面点击下载,通过window.location.href,就能直接下载到本地,但是当接口内部查询失败,则会通过json格式返回报错信息。这样就会出现一个问题,虽然用页面跳转的方式下载文件很方便,但是出现报错信息的时候会给你跳转到一个新的带json数据的页面,很明显,这对于用户体验是非常糟糕的!
实现
所以接下来的思路就是既能让接口返回文件数据的时候进行下载,又能在返回json信息的时候弹窗提示。
那么我首先想到的就是用ajax了,平时一般都使用jquery来发送ajax,但是这里就会出现一个很致命的问题,如果将ajax的接收数据类型设为json或者不设置,那么json数据能正常获取,但是获得文件返回的数据流下载到本地时,内容很明显产生了偏差。如果设置为blob类型,我就获取不到json格式数据。而且用jquery封装的ajax貌似不好获取返回数据的类型用于判断,所以暂时放弃。
不过在网上了解到了原生js发送ajax请求的方式,将返回数据都接受为blob类型,然后就能获取数据的响应头的数据类型,进而判断应该执行下载代码还是弹窗提示,当然在进入json格式部分时,还需要处理一道,把blob转换成json数据,到此就能正常获取异常信息了。代码如下:
var xhr = new XMLHttpRequest(); xhr.open('GET', url, true); // 也可以使用POST方式,根据接口 xhr.responseType = "blob"; // 返回类型blob xhr.onload = function () { // 请求完成 if (this.status === 200) { // console.log(this.response) let res_type = this.response.type if (res_type == 'application/octet-stream') { var blob = this.response; var reader = new FileReader(); reader.readAsDataURL(blob); // 转换为base64 reader.onload = function (e) { // 转换完成,创建一个a标签用于下载 var a = document.createElement('a'); let file_name = "file_name.bin" a.download = file_name; a.href = e.target.result; $("body").append(a); // 修复firefox中无法触发click a.click(); $(a).remove(); } } else if (res_type == "application/json") { // blob转json,获取异常信息 var enc = new TextDecoder('utf-8'); this.response.arrayBuffer().then(buffer = > { let data = JSON.parse(enc.decode(new Uint8Array(buffer))) || {}; // console.log(data) layer.msg(data['msg']) } ) } } else { layer.msg("请求异常!") } }; // 发送ajax请求 xhr.send()
标签:请求,json,xhr,ajax,blob,var,下载 From: https://www.cnblogs.com/lishuh/p/17237248.html