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);
                }
            }
        }
    }
相关推荐
子非鱼9214 小时前
【Ajax】原生Ajax与jQuery中的Ajax
xml·ajax·node.js·jquery
蜗牛学苑_武汉1 天前
浏览器中的事件循环
前端·javascript·chrome·ajax·软件工程·html5
awonw1 天前
[java][高级]Filter&Listener&Ajax
java·开发语言·ajax
supercool71 天前
Ajax学习
前端·学习·ajax
samroom2 天前
AJAX学习笔记总结
前端·学习·ajax
中庸之为德也,其至矣乎3 天前
uniapp 图片bug(图片为线上地址,url不变,内容更新)
开发语言·前端·javascript·css·ajax·uni-app
谈谈叭3 天前
Vue3+Data-V实现可视化大屏页面布局
javascript·css·vue.js·ajax·信息可视化·html·html5
盒马盒马6 天前
Ajax:跨域 & JSONP
前端·ajax
静止了所有花开6 天前
Ajax学习笔记
笔记·学习·ajax
小旺仔爱代码6 天前
AJAX和JSON
前端·ajax·json