Hzero实现xlsx模板文件导出功能

1、引入包文件

        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi</artifactId>
            <version>4.1.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
            <version>4.1.0</version>
        </dependency>

当然,如果有引入导入或导出组件,也是可以的。这个不限于Hzero,凡是SpringBoot都是可行的。

2、存放模板

这里要注意一下,我们存放模板可以放在项目的根目录外面,这样可以避免很多访问文件的问题,但是不方便部署,还可以放在项目的resoures 目录下

我在这个目录下创建一个目录temp,然后将模板存放在这个目录下。

3、创建Controller

我这里使用Post请求,原来使用get请求,前台无法转换格式文件,总是文件受损,换成post就正常了。

@ApiOperation(value = "自定义导出")
@Permission(level = ResourceLevel.ORGANIZATION)
@PostMapping("/excel/export")
public ResponseEntity excelExport(@ApiParam(value = "租户ID", required = true) @PathVariable Long organizationId,
                                  HttpServletResponse response,
                                  @RequestBody SoShipmentDetectionHead soShipmentDetectionHead) {
    soShipmentDetectionHead.setTenantId(organizationId);
    try {
        soShipmentDetectionHeadService.excelExport(response, soShipmentDetectionHead);
    } catch (IOException e) {
        log.error("导出失败", e);
        throw new CommonException("导出失败,请联系管理员");
    }
    return Results.success();
}

4、创建Service

这里不介绍业务逻辑,只说明技术问题

private void writeExcel(String path, HttpServletResponse response, String ctnNo) throws IOException {
    Resource resource = new ClassPathResource(path);
    if (resource.isReadable()) {
        OutputStream responseOutput = null;
        XSSFWorkbook workBook = null;
        try (InputStream inputStream = resource.getInputStream()) {
            workBook = new XSSFWorkbook(inputStream);
            Sheet sheetAt = workBook.getSheetAt(0);

            /** 业务逻辑 start **/
            SoShipmentDetectionLine line = new SoShipmentDetectionLine();
            line.setCartonNo(ctnNo);
            List<SoShipmentDetectionLine> lineList = soShipmentDetectionLineRepository.select(line);
            SoShipmentDetectionHead head = new SoShipmentDetectionHead();
            head.setModType("类型");
            head.setCustomer("客户名称");
            head.setDate(new Date());
            head.setCtnNo(ctnNo);
            createHead(lineList, ctnNo, head);
            writeSheet(sheetAt, head, lineList);
            /** 业务逻辑 end **/
            
            // 设置浏览器解析文件的mime类型,如果js中已设置,这里可以不设置
            response.setContentType("application/vnd.ms-excel;charset=gbk");
            // 设置此项,在IE浏览器中下载Excel文件时可弹窗展示文件下载
            response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(ctnNo + ".xlsx", "UTF-8"));
            // 允许浏览器访问header中的FileName
            response.setHeader("Access-Control-Expose-Headers", "FileName");
            // 设置FileName,转码防止中文乱码
            response.setHeader("FileName", URLEncoder.encode(ctnNo + ".xlsx", "UTF-8"));
            response.flushBuffer();
            workBook.write(response.getOutputStream());
        } catch (Exception e) {
            log.error("error", e);
        } finally {
            if (null != responseOutput) {
                responseOutput.close();
            }
            if (null != workBook) {
                workBook.close();
            }
        }
    } else {
        throw new CommonException("文件不存在!");
    }
}

这里要知道项目发布时是jar 包形式,一般的读取文件是无法读取jar包里的文件的,这时候要用ClassPathResource 读取文件,文件路径"temp" + File.separator + "testReport.xlsx" ,这样就能读取resoures 目录下的文件了,还有一点要记住,我们读取的文件是.xlsx ,所以要用XSSFWorkbook 创建文件对象,如果是.xls 要用HSSFWorkbook 创建对象。这非常重要,否则文件会损坏。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章