Springboot EasyExcel exporta el caso de Excel y el archivo no se puede abrir


  La exportación de datos es uno de los módulos clásicos de back-end. Desde el punto de interés original hasta el EasyExcel actual, etc., todos están trabajando arduamente para ayudar a los desarrolladores a reducir la brecha entre los datos y Excel. Pero en la exportación simple, también encontrará algunos problemas, así que escriba un artículo para registrarlo ~

introducción de fondo

El diagrama de flujo de exportación general es el siguiente:

组装数据
导出

Ensamblar datos: incluido el encabezado de la tabla,
la exportación de datos y estilos en Excel: flujo de archivos

encabezado y datos de easyexcel

Los documentos oficiales resumen los clásicos~

Encabezado: se divide en encabezado fijo y encabezado dinámico, y luego puede continuar dividiendo la versión simple y la versión compleja. Entre ellos, la versión compleja tiene tres o cuatro niveles de encabezados (anteriormente escriba poi codificado para explotar = _= ||)~ Un ejemplo es el siguiente ( fuente de la imagen ):
inserte la descripción de la imagen aquí
Datos: Cambia con el encabezado

Encabezamiento

Simple

inserte la descripción de la imagen aquí

Para corregir el encabezado , puede declarar una clase de entidad para la definición, de la siguiente manera:

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

Los encabezados de tabla dinámicos solo se pueden definir escribiendo código manualmente, de la siguiente manera:

// 外层数组,一个值代表一列
List<List<String>> headList = new ArrayList<List<String>>();
List<String> head0 = new ArrayList<String>();
head0.add("字符串标题");
headList.add(head0);

List<String> head1 = new ArrayList<String>();
head1.add("日期标题");
headList.add(head1);

List<String> head2 = new ArrayList<String>();
head2.add("数字标题");
headList.add(head2);

unir

inserte la descripción de la imagen aquí

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

método de exportación de proyectos web

En general, existen dos métodos de exportación para proyectos web:

  • Proporcione un enlace de descarga (asincrónico): primero genere Excel y cárguelo en el servidor oss/file, devuelva el enlace del archivo al front-end, y el front-end lo descargará por sí mismo
  • Flujo de archivos (sincrónico): genere Excel y métalo en el flujo de respuesta

Este artículo se centra principalmente en el método de transmisión de archivos. El código de ejemplo es el siguiente:

// 这里注意 有同学反应使用swagger 会导致各种问题,请直接用浏览器或者用postman
response.setContentType("application/vnd.ms-excel");
response.setCharacterEncoding("utf-8");
// 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
String fileName = URLEncoder.encode("测试", "UTF-8");
response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
EasyExcel.write(response.getOutputStream(), DownloadData.class).sheet("模板").doWrite(data());

El verdadero conocimiento proviene de la práctica.

Caso de encabezado dinámico simple

Este caso es relativamente simple, defina dinámicamente el encabezado de la tabla y cree datos de acuerdo con el tiempo del parámetro de solicitud, y devuélvalos al front-end en forma de flujo de archivos. El efecto es el siguiente:
representaciones
Agregue dependencias a pom:

<dependency>
	<groupId>com.alibaba</groupId>
	<artifactId>easyexcel</artifactId>
	<version>2.2.7</version>
</dependency>

El código de lógica de negocios es el siguiente:

@RestController
public class ResultController {
    
    
    
	@PostMapping(value = "/export")
    public void export(@RequestParam Integer time) {
    
    
    
    	try {
    
    
			HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();
			response.setHeader("Content-Disposition", "attachment; filename=export.xlsx");
	        // 响应类型,编码
	        response.setContentType("application/vnd.ms-excel;charset=utf-8");
	        response.setCharacterEncoding("utf-8");
			EasyExcel.write(response.getOutputStream()).head(getHead(time)).sheet("数据").doWrite(getData(time));
		} catch (IOException e) {
    
    
			log.error("导出问卷数据失败!错误信息为:{}", e.getMessage());
			e.printStackTrace();
		}
    }
    
    /**
     * 获取excel标题栏(姓名、手机号、提交时间)
     * @param questionnaireId
     * @return
     */
    private List<List<String>> getHead(Integer time) {
    
    
    	
    	// 外层数组,一个值代表一列
    	List<List<String>> headList = new ArrayList<List<String>>();
    	List<String> nameList = new ArrayList<String>();
    	nameList.add("姓名");
    	headList.add(nameList);
    	
    	List<String> telList = new ArrayList<String>();
    	telList.add("手机号");
    	headList.add(telList);
    	
    	List<String> submitDTList = new ArrayList<String>();
    	submitDTList.add("提交时间");
    	headList.add(submitDTList);
    	
    	for (int i = 0 ; i < time ; i ++ ) {
    
    
    		List<String> list = new ArrayList<String>();
    		list.add("动态标题" + i);
        	headList.add(list);
    	}
    	
    	return headList;
    }
    
    /**
	 * 获取excel表格数据
	 * @return
	 */
	private List<List<Object>> getData(Integer time) {
    
    
		
		// 将填写结果 + 提交时间合并为一行数据
		List<List<Object>> resultList = new ArrayList<List<Object>>();
		for (int i = 0 ; i < 3 ; i ++ ) {
    
    
			
			List<Object> list = new ArrayList<Object>();
			list.add("花卷" + i);
			list.add("1347000000" + i);
			list.add("2022-01-18 14:54:00");
			
			for (int j = 0 ; j < time ; j ++ ) {
    
    
	    		list.add("动态内容" + j);
	    	}
			
			resultList.add(list);
		}
		return resultList;
	}
  
}

problemas encontrados

Excel no se puede abrir durante la depuración conjunta front-end

Descripción del problema: la depuración con cartero en segundo plano está bien, ¡y Excel se puede abrir normalmente! Sin embargo, el Excel descargado durante la depuración frontal indica que está dañado y no se puede abrir. ! !
Consejos: Valiente (sin miedo a la muerte) cuestionando la interfaz, ¡su código tiene un ERROR!
solución: responseType: blobEl front-end necesita agregar configuraciones en solicitud y respuesta

( El siguiente pseudocódigo, concéntrese en la configuración de tipo de respuesta )

  1. La solicitud de front-end debe establecerresponseType为arraybuffer或blob
return request({
    
    
url: '/platform/export',
method: 'post',
responseType: 'blob',
headers: {
    
    
    'Content-Type': 'application/x-www-form-urlencoded'
},
data: qs.stringify(data)

})

  1. El front-end recibe la respuesta en formato blob y establece el tipo enapplication/msexcel
handleExport(){
    
    
  exportData({
    
    id: this.id}).then(res => {
    
    
    if(res){
    
    
      const fileName = this.name + '.xlsx';
        var blob = new Blob([res], {
    
    
        type: "application/msexcel;charset=utf-8",
      });
      const URL = window.URL || window.webkitURL;
      const downloadElement = document.createElement("a");
      const href = URL.createObjectURL(blob); // 创建下载的链接
      downloadElement.href = href;
      downloadElement.download = fileName; // 下载后文件名
      document.body.appendChild(downloadElement);
      downloadElement.click(); // 点击下载
      document.body.removeChild(downloadElement); // 下载完成移除元素
      URL.revokeObjectURL(href); // 释放掉blob对象
    }
  })
},

La interfaz de descarga de archivos a veces devuelve el flujo de archivos y a veces devuelve json

La dama de prueba hizo un pedido. Después de que se agotó el tiempo de espera del token, al hacer clic en el botón de descarga todavía se puede exportar normalmente. El contenido de Excel es el código de error json string devuelto por el sistema de autenticación de back-end =_=||. Lo busqué en línea y lo discutimos con los grandes. A continuación, no es recomendable encapsular el flujo de archivos en un método json de retorno unificado establecido por el sistema, y ​​finalmente sostener las delgadas piernas de la dama de front-end para encontrar una solución. Solución:
Después el front-end obtiene la respuesta, content-typese distingue
los documentos de referencia en línea
inserte la descripción de la imagen aquí



Continuará...

Supongo que te gusta

Origin blog.csdn.net/huhui806/article/details/122561103
Recomendado
Clasificación