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);
                }
            }
        }
    }
相关推荐
csdn_aspnet1 天前
JavaScript AJAX 库
javascript·ajax
林的快手2 天前
伪类选择器
android·前端·css·chrome·ajax·html·json
还是鼠鼠2 天前
详细介绍:封装简易的 Axios 函数获取省份列表
前端·javascript·vscode·ajax·前端框架
不会&编程5 天前
第四章 Vue 中的 ajax
前端·vue.js·ajax
Leven1995276 天前
Spark 性能优化 (三):RBO 与 CBO
ajax·性能优化·spark
还是鼠鼠8 天前
使用XMLHttpRequest发送带查询参数的 GET 请求并动态展示数据
前端·javascript·vscode·ajax·bootstrap
木蓝茶陌*_*8 天前
fetch() 与 XMLHttpRequest 的差异
xmlhttprequest·fetch的基本用法·fetch与xhr的差异
还是鼠鼠11 天前
(案例)如何使用 XMLHttpRequest 发送带查询参数的请求查询地区
前端·javascript·vscode·ajax·前端框架·html5
P7进阶路11 天前
Ajax:重塑Web交互体验的人性化探索
前端·javascript·ajax
吃蛋糕的居居11 天前
疯狂前端面试题(四)
前端·javascript·chrome·ajax·正则表达式·firefox·html5