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);
                }
            }
        }
    }
相关推荐
Run Freely9373 天前
Ajax-day2(图书管理)-弹框显示和隐藏
前端·javascript·ajax
xkroy4 天前
ajax
前端·javascript·ajax
元亓亓亓4 天前
JavaWeb--day3--Ajax&Element&路由&打包部署
android·ajax·okhttp
Yvonne爱编码4 天前
AJAX入门-URL、参数查询、案例查询
前端·javascript·ajax
lwprain5 天前
龙蜥8.10中spark各种集群及单机模式的搭建spark3.5.6(基于hadoop3.3.6集群)
大数据·ajax·spark
知识分享小能手5 天前
React学习教程,从入门到精通,React AJAX 语法知识点与案例详解(18)
前端·javascript·vue.js·学习·react.js·ajax·vue3
Yvonne爱编码6 天前
构建高效协作的桥梁:前后端衔接实践与接口文档规范详解
前端·git·ajax·webpack·node.js
William_cl6 天前
MVC 中 AJAX 与前后端交互深度实战(含独家避坑与场景化方案)
ajax·mvc·交互
Yvonne爱编码7 天前
AJAX入门-AJAX 概念和 axios 使用
前端·javascript·ajax·html·js
闯闯桑7 天前
Spark 中spark.implicits._ 中的 toDF和DataFrame 类本身的 toDF 方法
大数据·ajax·spark·scala