Loading

关于 EasyExcel 导出下载文件需要知道的那些事

Part 1. 前言

好记性不如烂笔头,本着自己已经在开发过程中花费了大把时间去检索“为什么不行”以及“该怎么办”的检索过程,故在这里进行整理和归纳,也将所参考的文章罗列在Part 0中,部分解决方式也经过了校验,方便大家在遇到相同问题时可以方便在茫茫的 cv 博客中找到真正能解决问题的好文(滑稽.jpg

讲讲我为什么会遇到这个问题,首先业务测使用的文件下载工具采用的是 EasyExcel,这里放上 EasyExcel文档方便大家检索使用,我采用的是最简单的写的方式,需要明确一点,写 excelweb 端下载 excel 的区别:

Part 2. EasyExcel 写文件

在最简单的写 excel 中,EasyExcel 所需要的条件即文件名/文件路径、表头数据、sheet 名以及写入的数据,以官网示例为例如下:

// WriteTest.java
EasyExcel.write(fileName, DemoData.class).sheet("模板").doWrite(data());

private List<DemoData> data() {
    List<DemoData> list = new ArrayList<DemoData>();
    for (int i = 0; i < 10; i++) {
        DemoData data = new DemoData();
        data.setString("字符串" + i);
        data.setDate(new Date());
        data.setDoubleData(0.56);
        list.add(data);
    }
    return list;
}

// DemoData.java
import lombok.Data;

@Data
public class DemoData {
    @ExcelProperty("字符串标题")
    private String string;
    @ExcelProperty("日期标题")
    private Date date;
    @ExcelProperty("数字标题")
    private Double doubleData;
}

需要注意的是,这里说的是文件名或文件路径,当 fileName 具体到文件路径时,excel 文件写后即写在该路径下,若 fileName 为文件名时,会写在该项目的根目录下

以上两种方式的写 excel ,都并不是 web 端下载的方式(即浏览器下载文件的形式)来得到的,这是我最开始误会的地方

Part 3. EasyExcel web 端写文件

在实现 web 端的写文件之前,这里需要先明确一下自己 web 页面写文件的方式是哪一种,我这里的业务采用的是 jQuery 的 Ajax 的 Post 请求方式,过程里访问接口一直都能够正常访问,但就是没有执行 web 端的文件下载,接口返回的尽是些乱码,于是我就踏上了不断检索的道路,很庆幸检索到和我遇到相同问题的道友,并进一步验证了他的说法,下面就来谈谈为什么可以访问接口但是返回乱码且不执行 web 端下载的问题:

首先 jQuery 所封装的 ajax 它所能接收的数据类型需要明确一下,从下图文档中可以看到,dataType 在预期的接受类型中,并不包含有二进制流数据 blob,所以直接通过 $.ajax 的方式是无法满足预期需求

网上有提供通过更新 xhr 的方式改变 $.ajaxresponseType解决方案,我验证了下似乎没有预期效果,因为不接受 blob 类型直接进 error 的回调函数中,报错信息如下:

DOMException: Failed to read the 'responseText' property from 'XMLHttpRequest': The value is only accessible if the object's '' is '' or 'text' (was 'blob').

这边也就不再多余的赘述,如果有成功的验证,欢迎留言指正我的误解,谢谢大家,下面介绍能够正常使用的两种方式

  • 通过 form 表单的形式进行提交

    var url = 'xxxxxxxxxxxx';
    var form = document.createElement('form');
    var xxx = document.createElement('input');
    
    form.setAttribute('style', 'display:none');
    form.setAttribute('target', '');
    form.setAttribute('method', 'post');
    form.setAttribute('action', url);
    
    xxx.type = 'hidden';
    xxx.name = 'xxx';
    xxx.value = param ? param : '';
    form.appendChild(xxx);
    
    // ...
    
    document.body.appendChild(form);
    form.appendChild(xxx);
    
    // ...
    
    form.submit();
    form.remove();
    
  • 通过原生 js 实现 ajax 的方式,即原生的XMLHttpRequest对象发出 HTTP 请求,对接收的数据先进行 createObjectURL 的包装,再通过以 <a>标签下载链接的方式触发 web 端下载该文件

    var params = {xxx:xxx};
    
    var url = 'xxxxxxxxxxxx';
    var xhr = new XMLHttpRequest();
    xhr.open('POST', url, true); // 也可以使用POST方式,根据接口
    xhr.responseType = 'blob'; // 返回类型blob
    xhr.onload = function () {
    	if (this.status === 200) {
    		var blob = this.response;
    		const url = window.URL.createObjectURL(blob);
    		const a = document.createElement('a');
    		a.style.display = 'none';
    		a.href = url;
    		a.download = 'xxx.xlsx';
    		document.body.appendChild(a);
    		a.click();
    		window.URL.revokeObjectURL(url);
    	}
    };
    // 发送ajax请求
    xhr.send(params);
    

Part 0. Reference

  1. EasyExcel 使用说明 - 如何使用 EasyExcel
  2. web页面实现文件下载的几种方法 - 阐述 web 端文件下载方式
  3. EasyExcel实现下载Excel(解决无法从浏览器下载问题) - jQuery 的 ajax 无法接收二进制流
  4. Handle file download from ajax post
  5. Receiving binary data using JavaScript typed arrays - 二进制文件流
  6. jQuery.ajax() API 文档 - ajax API 文档
  7. 关于javascript:使用jQuery的ajax方法将图片检索为blob
  8. AJAX 之 XHR, jQuery, Fetch 的对比
posted @ 2021-07-25 21:57  诀别、泪  阅读(1919)  评论(0编辑  收藏  举报