XMLHttpRequest和FormData下载文件,ajax下载文件

1、前端请求只做下载功能

javascript 复制代码
function downloadDatas3() {
    // 封装请求参数
    let formData = new FormData();
    formData.append('page', '1');
    formData.append('rows', '10');
    // 创建xhr对象
    let xhr = new XMLHttpRequest();
    xhr.open('POST', 'http://127.0.0.1:8080/getData');
    // xhr.setRequestHeader('Content-Type', 'application/json');
    xhr.responseType = 'blob';// 设置响应类型为blob,以便处理二进制数据
    xhr.send(formData);
    xhr.onload = function () {
        if (this.status == 200) {
            let blob = this.response;
            let a = document.createElement('a');
            let url = window.URL.createObjectURL(blob);
            //获取文件名称
            let fileName = decodeURI(xhr.getResponseHeader('Content-Disposition'));
            //截取=字符串后面的内容
            let str = fileName.match(/=(\S*)/)[1];
            a.href = url; // 设置链接源
            a.download = str; // 设置下载文件名
            document.body.appendChild(a); // 将链接加入到DOM
            a.click(); // 触发下载
            a.remove(); // 删除链接
            window.URL.revokeObjectURL(url); // 释放URL对象
        }
    }
    xhr.onerror = function (event) {
        alert('文件下载失败!');
    }
}

2、前端请求下载失败,提示失败原因

javascript 复制代码
function downloadDatas3() {
    // 封装请求参数
    let formData = new FormData();
    formData.append('page', '1');
    formData.append('rows', '10');
    // 创建xhr对象
    let xhr = new XMLHttpRequest();
    xhr.open('POST', 'http://127.0.0.1:8080/getData');
    // xhr.setRequestHeader('Content-Type', 'application/json');
    xhr.responseType = 'blob';// 设置响应类型为blob,以便处理二进制数据
    xhr.send(formData);
    xhr.onload = function () {
        if (this.status == 200) {
            let blob = this.response;
            // 根据type类型,区分是下载文件还是下载失败原因
            if ('text/html' == blob.type) {
                let fileReader = new FileReader(); //FileReader可以读取Blob内容
                fileReader.readAsText(blob); //二进制转换成text
                fileReader.onload = function () {  //转换完成后,调用onload方法
                    let result = fileReader.result;  //result 转换的结果
                    let data = JSON.parse(result);
                    alert(data.msg);
                }
                return;
            }
            let a = document.createElement('a');
            let url = window.URL.createObjectURL(blob);
            //获取文件名称
            let fileName = decodeURI(xhr.getResponseHeader('Content-Disposition'));
            //截取=字符串后面的内容
            let str = fileName.match(/=(\S*)/)[1];
            a.href = url; // 设置链接源
            a.download = str; // 设置下载文件名
            document.body.appendChild(a); // 将链接加入到DOM
            a.click(); // 触发下载
            a.remove(); // 删除链接
            window.URL.revokeObjectURL(url); // 释放URL对象
        }
    }
    xhr.onerror = function (event) {
        alert('文件下载失败!');
    }
}

后端处理逻辑

下载文件使用响应头为 Content-Type=application/octet-stream

下载文件失败,使用响应头为 Content-Type=text/html

前端根据不同的响应头类型,来区分是下载文件,还是失败原因。

java 复制代码
    @PostMapping("/getData")
    public void getData(HttpServletRequest request, HttpServletResponse response) {
        Map<String, Object> map = new HashMap<>();
        try {
            // 请求参数
            String currPage = request.getParameter("page");
            String pageSize = request.getParameter("rows");

            // 下载文件
            String fileName = "测试.xlsx";
            // 设置服务器输出的编码为UTF-8
            response.setCharacterEncoding("UTF-8");
            // 设置response的Header
            response.addHeader("Content-Type", "application/octet-stream");
            response.addHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(fileName, "UTF-8"));
            ServletOutputStream os = response.getOutputStream();

            // 响应输出流
            int len;
            byte[] buffer = new byte[4096];
            FileInputStream fis = new FileInputStream("/tmp/" + fileName);
            while ((len = fis.read(buffer)) != -1) {
                os.write(buffer, 0, len);
                os.flush();
            }
            os.close();
            fis.close();

            map.put("code", 200);
            map.put("msg", "下载成功");
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            map.put("code", 500);
            map.put("msg", "下载数据异常!");
        } finally {
            // 处理失败
            if (200 != (int) map.get("code")) {
                try {
                    String msg = JSON.toJSONString(map);
                    response.setContentType("text/html; charset=UTF-8");
                    ServletOutputStream os = response.getOutputStream();
                    os.write(msg.getBytes(StandardCharsets.UTF_8));
                    os.flush();
                    os.close();
                } catch (IOException e) {
                    log.error(e.getMessage(), e);
                }
            }
        }
    }
相关推荐
十六ᵛᵃᵉ1 天前
day6_FlinkSQL实战
java·redis·ajax
微臣愚钝2 天前
【12】Ajax的原理和解析
前端·javascript·ajax
weixin_443566983 天前
39-Ajax工作原理
前端·ajax
东东__net4 天前
26_ajax
前端·javascript·ajax
最初@7 天前
el-table + el-pagination 前端实现分页操作
前端·javascript·vue.js·ajax·html
微臣愚钝7 天前
【13】Ajax爬取案例实战
前端·javascript·ajax
坐望云起8 天前
ASP.NET Web的 Razor Pages应用,ajax调用记录以及Cookie配置
前端·ajax·asp.net·cookie·xsrf/csrf
前端_学习之路9 天前
axios--源码解析
java·开发语言·javascript·ajax
lee57610 天前
用Promise实现ajax的自动重试
前端·javascript·ajax
NicolasCage11 天前
简单的封装一下axios
vue.js·ajax·axios