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);
                }
            }
        }
    }
相关推荐
LongtengGensSupreme19 小时前
开放所有跨域 ----前端和后端
前端·后端·ajax·vue·api·jquery
雨雨雨雨雨别下啦2 天前
ajax和axios到底是什么
前端·ajax·okhttp
C_心欲无痕2 天前
网络相关 - Fetch 与 Ajax 请求讲解
前端·网络协议·ajax·fetch
qq_406176144 天前
什么是模块化
开发语言·前端·javascript·ajax·html5
小笔学长6 天前
XMLHttpRequest 对象:传统的网络请求方式
javascript·xmlhttprequest·前端开发·网络请求实战·跨域问题解决
释怀不想释怀6 天前
vue(登录,退出,浏览器本地存储机制)
前端·javascript·vue.js·ajax·html
chilavert3187 天前
技术演进中的开发沉思-284 计算机原理:二进制核心原理
javascript·ajax·计算机原理
Beginner x_u7 天前
从 Promise 到 async/await:一次把 JavaScript 异步模型讲透
javascript·ajax·promise·异步·async await
‿hhh7 天前
综合交通运行协调与应急指挥平台项目说明
java·ajax·npm·json·需求分析·个人开发·规格说明书
释怀不想释怀8 天前
Ajax,vue生命周期(自动加载页面发出请求)Axios
前端·javascript·ajax