标签:+= http状态码 改进 数据 异步 href 相对 his 包含
本篇随笔说明
警告:本文不适合找“XMLHttpRequest下载文件方法”的人群阅读(尽管我的标题包含了这些关键字),这个人群看了本文后可能会有些懵。
这里没有完整的XMLHttpRequest下载文件的代码,只是为了解决特定问题而摘出来部分代码,因是从项目中提取的,故代码中也包含了用到的一些其它框架。
问题描述
在下载文件的程序中,此处我们用到的是excel导出,此时如果服务器没有合适的数据可以供导出,我们原来的方案,就是导出一个只含有头部列头的excel,在前端还是依然能够下载该文件,用户看到一个不含他想要的数据的文件,大概会懵掉,对用户不太友好。后来想着,要不就把错误提示扔到excel里,想想还是不友好,以致有了下面的改进方案:
解决方案
在没有合适数据可导出或发生一些可预知的错误时,服务器返回一个错误提示的json数据。此时前后端需要进行一些调整,如下。
用XMLHttpRequest下载文件,所以设置XMLHttpRequest.responseType = "blob",此时如果服务器返回一个json数据,前端无法通过一般的方案解析出json数据;
解决方案:服务器端返回一个特定的http状态码,前端遇到该状态码,则进行特殊处理。
后端返回一个206的错误码及一个json数据
//为了更清晰的说明问题,此处把其它代码都去掉了,只保留返回错误情况的代码 public IActionResult GetPBbackDtoPrintListForPB(GetWorkTimeArrangeInput args) { Response.StatusCode = 206; string msg = "没有数据!请确保筛选条件下有数据!"; return Json(new BizResult(){ Success = false, Message = msg }); }
前端处理json的部分,不能像正常返回json数据那样用JSON.parse(result)处理,或直接result.success,因为这样是取不到数据的,且运行会有未定义的错误。需要用如下方法,从流中读取。
if (this.status === 206) {//处理错误提示 var result = this.response; if (result.type === ‘application/json‘) { var reader = new FileReader(); reader.readAsText(result, ‘utf-8‘); reader.onload = (e) => { var jsonData = JSON.parse(reader.result); if (!jsonData.success) { $.messager.alert("警告", jsonData.message); } } }
相对完整的前端代码,因用到其它JS框架,如用不上需剔除部分代码,还有一些传值封装,代码太多,而且分散在各处,这里不全部列出来
/** * 异步下载文件 依赖easyui的进度条 * */ downloadAsync: function (method, url, data,contentType, displayfileName, callback) { if (!displayfileName) displayfileName = ‘‘; if (!method) method = "get"; method = method.toLowerCase(); if (!url) throw "url mast has value"; if (method != "post" && method != "get") method = "get"; var xhr = new XMLHttpRequest(); var sendData = null; if (data && (typeof (data) == "object" || typeof (data) == "string")) { if (contentType.toLowerCase() ==="application/json") { sendData = JSON.stringify(data); } else if (method.toLowerCase() === "get") { //参数追加到url上 var params; if (typeof (data) == "string") params = data; else params = $.param(data); var ls = url.indexOf(url.length); switch (ls) { case "?": case "&": url += params break; default: if (url.indexOf(‘?‘) < 0) { url += "?" + params; } else { url += "&" + params; } break; } } else { sendData = $.param(data); } } xhr.open(method, url, true); // 也可以使用POST方式,根据接口 xhr.setRequestHeader(‘content-type‘, contentType); xhr.responseType = "blob"; // 返回类型blob $.messager.progress({ msg: ‘下载中。。。‘, interval: 0 }); var bar = $.messager.progress(‘bar‘); //进度事件 xhr.onprogress = function (ev) { if (ev.lengthComputable) { progress = ev.loaded / ev.total; //更新进度条 bar.progressbar(‘setValue‘, parseFloat(progress, 2) * 100); } }; // 定义请求完成的处理函数 xhr.onload = function () { // 请求完成 if (this.status === 200) { // 返回200 var blob = this.response; var reader = new FileReader(); reader.readAsDataURL(blob); // 转换为base64,可以直接放入a表情href reader.onload = function (e) { // 转换完成,创建一个a标签用于下载 var a = document.createElement(‘a‘); if (!displayfileName || typeof (displayfileName) != ‘string‘) displayfileName = new Date().getTime + ‘.txt‘; console.log(displayfileName); a.download = displayfileName; a.href = e.target.result; $("body").append(a); // 修复firefox中无法触发click a.click(); $(a).remove(); if (typeof (callback) == "function") callback(); }; } else if (this.status === 206) {//处理错误提示 var result = this.response; if (result.type === ‘application/json‘) { var reader = new FileReader(); reader.readAsText(result, ‘utf-8‘); reader.onload = (e) => { var jsonData = JSON.parse(reader.result); if (!jsonData.success) { $.messager.alert("警告", jsonData.message); } } } } else { errortitle = "错误"; error = "导出错误"; switch (this.status) { case 404: error += " 页面找不到"; break; case 400: error += " 导出参数不对"; break; case 500: error += " 导出数据失败"; break; default: break; } $.messager.alert(errortitle, error); } $.messager.progress(‘close‘); }; xhr.onreadystatechange = function (ev) { } // 发送ajax请求 xhr.send(sendData); }
XMLHttpRequest下载文件方法中添加处理服务器返回json格式的错误提示信息
标签:+= http状态码 改进 数据 异步 href 相对 his 包含
原文地址:https://www.cnblogs.com/stone2012/p/12719972.html