POI动态导出Excel,后台返回文件流,前端responseType格式下载

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/baidu_28068985/article/details/83035727

针对各个表的数据导出,实现的代码往往相似,出于这个目的,开启自己代码简略之旅。本文是针对.xls的excel文件。

1、思路描述

    ①、确定各个模板的.xls文件格式

    ②、定义模板的存在的参数,如第一行的参数,第二行的参数等

    ③、excel文件中针对行 列定位方式,如 (0, 0, 0,0)

    ④、处理从数据库获取的数据格式key-value 如 name 小明

    如下图,本篇幅就围绕下图展开:

2、代码如下:(向前端返回的下载路径)

controller类的方法

 @ApiOperation(value = "导出地址数据")
    @PostMapping(value="/exportAddresses")
    public ApiResponse<Object> exportAddresses(){
        ApiResponse<Object> resp = new ApiResponse<Object>();

        // 数据库表对应的字段
        String[] titles = new String[] {"id","name","pid","code","description"}; 
        List<Map<String,Object>> objList = new ArrayList<>();
        
        // 数据库表对应的数据
        List<AddressVo> list = addressService.exportAddresses();
        for(AddressVo item : list){
            Map<String,Object> tempMap = new HashMap<>();
            tempMap.put("id", item.getId());
            tempMap.put("name", item.getName());
            tempMap.put("pid", item.getPid());
            tempMap.put("code", item.getCode());
            tempMap.put("description", item.getDescription());
            objList.add(tempMap);
        }
        String path = FileUtil.exportExcel("地址树",titles,objList);
        System.out.println("path="+path);
        if(path == null){
            resp.error("导出失败!");
        }
        resp.ok("导出成功!").setData(path);

        return resp;
    }

FileUtil 类

public class FileUtil <T> {

    // 挂在项目的某文件夹下
	public static final String REPORT_PATH ="templates"+ File.separator;


/**
	 * 导出数据
	 * @auther xuguocai
	 * @param fileName 文件名
	 * @param titles  字段名
	 * @param result 导出数据
	 * @throws IOException
	 */
	public static String exportExcel(String fileName,String[] titles,List<Map<String,Object>> result){
		HSSFWorkbook wb;
		FileOutputStream fos;
		String tempName = fileName;
		try {
			Date date = new Date();
			SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
			fileName +="_"+df.format(date)+".xls";

			fos = new FileOutputStream(FileUtil.REPORT_PATH + fileName);
			wb= new HSSFWorkbook();

			HSSFSheet sh = wb.createSheet();

			// 设置列宽
			for(int i = 0; i < titles.length-1; i++){
				sh.setColumnWidth( i, 256*15+184);
			}

			// 第一行表头标题,CellRangeAddress 参数:行 ,行, 列,列
			HSSFRow row = sh.createRow(0);
			HSSFCell cell = row.createCell(0);
			cell.setCellValue(new HSSFRichTextString(tempName));
			cell.setCellStyle(fontStyle(wb));
			sh.addMergedRegion(new CellRangeAddress(0, 0, 0,titles.length-1));

			// 第二行
			HSSFRow row3 = sh.createRow(1);

			// 第二行的列
			for(int i=0; i < titles.length; i++){
				cell = row3.createCell(i);
				cell.setCellValue(new HSSFRichTextString(titles[i]));
				cell.setCellStyle(fontStyle(wb));
			}

			//填充数据的内容  i表示行,z表示数据库某表的数据大小,这里使用它作为遍历条件
			int i = 2, z = 0;
			while (z < result.size()) {
				row = sh.createRow(i);
				Map<String,Object> map = result.get(z);
				for(int j=0;j < titles.length;j++) {
					cell = row.createCell(j);
					if(map.get(titles[j]) !=null) {
						cell.setCellValue(map.get(titles[j]).toString());
					}else {
						cell.setCellValue("");
					}
				}
				i++;
				z++;
			}

			wb.write(fos);
			fos.flush();
			fos.close();
			return FileUtil.REPORT_PATH + fileName;
		}catch (Exception e){
			e.printStackTrace();
		}
		return null;
	}

}

3、向前端返回文件流的形式

controller类

@ApiOperation(value = "导出地址数据")
    @PostMapping(value="/exportAddresses")
    public ApiResponse<Object> exportAddresses(HttpServletResponse response){
        ApiResponse<Object> resp = new ApiResponse<Object>();

        String[] titles = new String[] {"id","name","pid","code","description"};
        List<Map<String,Object>> objList = new ArrayList<>();

        List<AddressVo> list = addressService.exportAddresses();
        for(AddressVo item : list){
            Map<String,Object> tempMap = new HashMap<>();
            tempMap.put("id", item.getId());
            tempMap.put("name", item.getName());
            tempMap.put("pid", item.getPid());
            tempMap.put("code", item.getCode());
            tempMap.put("description", item.getDescription());
            objList.add(tempMap);
        }
        try {
            FileUtil.exportExcel(response,"地址树",titles,objList);
            resp.ok("导出成功!");
        }catch (Exception e){
            e.printStackTrace();
            resp.error("导出失败!");
        }
        return resp;
    }

FileUtil 类

public static void exportExcel(HttpServletResponse response,String fileName,String[] titles,List<Map<String,Object>> result){
   HSSFWorkbook wb;
   OutputStream output = null;
   String tempName = fileName;
   try {
      Date date = new Date();
      SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
      fileName +="_"+df.format(date)+".xls";

      wb= new HSSFWorkbook();
      HSSFSheet sh = wb.createSheet();

      // 设置列宽
      for(int i = 0; i < titles.length-1; i++){
         sh.setColumnWidth( i, 256*15+184);
      }

      // 第一行表头标题,CellRangeAddress 参数:行 ,行, 列,列
      HSSFRow row = sh.createRow(0);
      HSSFCell cell = row.createCell(0);
      cell.setCellValue(new HSSFRichTextString(tempName));
      cell.setCellStyle(fontStyle(wb));
      sh.addMergedRegion(new CellRangeAddress(0, 0, 0,titles.length-1));

      // 第二行
      HSSFRow row3 = sh.createRow(1);

      // 第二行的列
      for(int i=0; i < titles.length; i++){
         cell = row3.createCell(i);
         cell.setCellValue(new HSSFRichTextString(titles[i]));
         cell.setCellStyle(fontStyle(wb));
      }

      //填充数据的内容  i表示行,z表示数据库某表的数据大小,这里使用它作为遍历条件
      int i = 2, z = 0;
      while (z < result.size()) {
         row = sh.createRow(i);
         Map<String,Object> map = result.get(z);
         for(int j=0;j < titles.length;j++) {
            cell = row.createCell(j);
            if(map.get(titles[j]) !=null) {
               cell.setCellValue(map.get(titles[j]).toString());
            }else {
               cell.setCellValue("");
            }
         }
         i++;
         z++;
      }

      output = response.getOutputStream();
      response.reset();
      response.setHeader("Content-disposition", "attachment; filename="+fileName);
      response.setContentType("application/msexcel");
      wb.write(output);
      output.flush();
      output.close();
   }catch (Exception e){
      e.printStackTrace();
   }
}

4、下载,后台返回的是文件流

  responseType详解

数据类型
’ ‘     DOMString (这个是默认类型),是一个UTF-16字符串。由于JavaScript已经使用了这样的字符串,所以DOMString 直接映射到 一个String
arraybuffer  ArrayBuffer对象,表示通用的、固定长度的原始二进制数据缓冲区。ArrayBuffer 不能直接操作,而是要通过类型数组对象或 DataView 对象来操作,它们会将缓冲区中的数据表示为特定的格式,并通过这些格式来读写缓冲区的内容。详解:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer
blob  Blob对象,表示不可变的类似文件对象的原始数据。Blob表示不一定是JavaScript原生形式的数据
document  Document对象,表示任何在浏览器中已经加载好的网页,并作为一个入口去操作网页内容(也就是DOM tree)。DOM tree包括像 <body> 、<table>这样的还有其他的元素。它提供了全局操作document的功能,像获取网页的URL和在document里创建一个新的元素
json   JavaScript object, parsed from a JSON string returned by the server
text DOMString

 ①、不携带参数请求,

// url 向后台请求的接口 ,fileName 下载赋予的文件名
downloadFile(url , fileName){
      this.$ajax.get(url, {responseType: 'arraybuffer'}).then((res) => {
        let data = res.data
        if (!data) {
          return
        }
        let url = window.URL.createObjectURL(new Blob([data]))
        let link = document.createElement('a')
        link.style.display = 'none'
        link.href = url
        link.download = fileName;
        document.body.appendChild(link)
        link.click()
        window.URL.revokeObjectURL(link.href);
      }).catch(err=>{
      })
    },

②携带参数请求,可以将参数放进请求路径中,如url=/api/department/downloadDepartmentTemplate?isVirtual=0

5、总结

以上简单介绍了动态生成excel文件和向前端传文件路径 向前端传文件流的两种形式。仅供自己学习和代码积累。简简单单,首要原则是方便自己,谢谢。

猜你喜欢

转载自blog.csdn.net/baidu_28068985/article/details/83035727