1 由项目需要,需要一个下载动态模板压缩包的功能,实现过程分一下几步
1)加载模板文件,把模板文件封装成一个workbook对象,根据业务需要把相关数据写到相应的位置
2)调用workbook对象的write方法,把更改后的Excel文件通过输出流写到一个临时Excel文件中
3)由于java JDK自带的ZipoutputStream中文会乱码,使用apache的ZipoutputStream压缩临时Excel文件
4)把Excel压缩文件以字节流的形式写到客户端
5)关闭各种流
6)清除Excel临时文件及压缩包
以下是实现代码:
Workbook wb = null; try { List<DivisionMapDto> divisionMapList = divisionMapController.getDivisionMapInfo(memberId, taskId); if(null == divisionMapList || divisionMapList.size() == 0){ throw new BadRequestException("400","请维护科室映射关系"); } String excelTemplateName = reportType + "ValidateTemplate.xlsx"; FileSystemConfigReaderImpl configReader = (FileSystemConfigReaderImpl) ConfigUtil.getConfigReader(); String basePath = configReader.getBasePath(); String separator = System.getProperty("file.separator"); basePath = basePath + separator; String fileName = basePath + excelTemplateName; wb = new XSSFWorkbook(new FileInputStream(fileName)); Sheet sheet = wb.getSheetAt(0); if(sheet == null){ throw new BadRequestException("400","下载报表模板sheet对象为空,报表类型,reportType=" + reportType); } int[] divisionColumnIndexs = ExcelColumnMatchUtils.getDivsionInfoLocation(reportType); if(divisionColumnIndexs[0] == -1 || divisionColumnIndexs[1] == -1){ throw new BadRequestException("400","执行科室编码和执行科室名称在模板中的列索引错误,请联系管理员维护,报表类型,reportType=" + reportType); } //excel当前行取用户维护科室映射关系第writingCount条数据 DivisionMapDto divisionMapDto = null; Cell cell = null; Row row = null; int rowNum = sheet.getLastRowNum(); for(int i = 0 ; i < divisionMapList.size(); i++){ divisionMapDto = divisionMapList.get(i); if(null == divisionMapDto){ continue; } rowNum++; row = sheet.createRow(rowNum); //执行科室编码 cell = row.createCell(divisionColumnIndexs[0]); cell.setCellValue(divisionMapDto.getLocalCode()); //执行科室名称 cell = row.createCell(divisionColumnIndexs[1]); cell.setCellValue(divisionMapDto.getLocalName()); //国家科室编码 if(divisionColumnIndexs[2] != -1){ cell = row.createCell(divisionColumnIndexs[2]); cell.setCellValue(divisionMapDto.getStandardCode()); } //国家科室名称 if(divisionColumnIndexs[3] != -1){ cell = row.createCell(divisionColumnIndexs[3]); cell.setCellValue(divisionMapDto.getStandardName()); } } String reportName = null; try{ reportName = reportListController.getReportNameByReportType(reportType); } catch (CarsmartException e){ logger.error("根据报表类型查询报表名称发生异常", e); } reportName = reportName == null ? "报表" : reportName; String tempFileName = basePath + reportName + ".xlsx"; FileOutputStream fos = new FileOutputStream(new File(tempFileName)); wb.write(fos); reportName += ".zip"; String zipFileName = basePath + reportName; try{ zipFile(zipFileName, tempFileName); } catch (Exception e){ logger.error("压缩文件发生异常", e); } //文件名编码转换解决在IE下乱码的问题 //URLEncoder.encode(reportName, "UTF-8") 这种方式也可以解决中文乱码 response.addHeader("Content-Disposition", "attachment; filename=" + new String(reportName.getBytes("gb2312"), "iso-8859-1")); response.setContentType("application/octet-stream"); OutputStream outputStream = response.getOutputStream(); BufferedInputStream bin = new BufferedInputStream(new FileInputStream(zipFileName)); byte[] buf = new byte[1024]; int len = 0; while((len = bin.read(buf)) > 0){ outputStream.write(buf,0,len); } outputStream.flush(); outputStream.close(); bin.close(); //删除压缩文件 File file = new File(zipFileName); if(file.exists()){ file.delete(); } //删除临时文件 file = new File(tempFileName); if(file.exists()){ file.delete(); } return null; } catch (CarsmartException e) { logger.error("导出错误详细信息发生异常", e); return null; } catch (IOException e){ logger.error("导出错误详细信息发生IO异常", e); return null; }
/** * @Description 压缩文件实现 * @param out * @param f * @param base * @param first * @throws Exception */ private void zip(ZipOutputStream out, File f, String base, boolean first) throws Exception { if (first) { if (f.isDirectory()) { out.putNextEntry(new ZipEntry("/")); base = base + f.getName(); first = false; } else base = f.getName(); } if (f.isDirectory()) { File[] fl = f.listFiles(); base = base + "/"; for (int i = 0; i < fl.length; i++) { zip(out, fl[i], base + fl[i].getName(), first); } } else { out.putNextEntry(new ZipEntry(base)); FileInputStream in = new FileInputStream(f); int b; while ((b = in.read()) != -1) { out.write(b); } in.close(); } } /** * @Description 压缩文件 * @param zipFileName * @param inputFileName * @throws Exception */ private void zipFile(String zipFileName, String inputFileName) throws Exception { ZipOutputStream out = new ZipOutputStream(new FileOutputStream(zipFileName)); out.setEncoding("gbk");// 设置的和文件名字格式一样或开发环境编码设置一样的话就能正常显示了 File inputFile = new File(inputFileName); zip(out, inputFile, "", true); out.close(); }