需求分析
1.有几个Excel文件,是通过Excel poi 读数据库生成的outputStream流文件,目标是将这几个output流文件,通过zip打成压缩包,通过servlet流,返回给浏览器,最终通过浏览器完成对压缩包的下载。
2.想要实现的是在内存中对文件进行压缩,而不生成实体文件。
解决方案
思路
首先,将创建的excel outputStream流放在字节数组中;
通过迭代,通过zip工具类,将字节数组传递给zipEntry,并给该文件文件名
最后将zipEntry放入到zipOutputStream中
note
1、zipOutputStream 是zip工具(java.util.zip.ZipOutputStream)中的一个类,接收ByteArrayOutputStream;
2、部分代码使用了 hutools包中的Excel库;
代码
part1:写入Excel 并转成字节流
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| ByteArrayOutputStream byteArrayInputStream = new ByteArrayOutputStream(); ExcelWriter writer = ExcelUtil.getWriter(); writer.addHeaderAlias("studentNumber", "学号"); writer.addHeaderAlias("studentName", "姓名"); writer.addHeaderAlias("examPaperId", "试卷编号"); writer.addHeaderAlias("questionBh", "题目编号"); writer.addHeaderAlias("questionName", "题目名称"); writer.addHeaderAlias("stage", "阶段"); writer.addHeaderAlias("questionDesc", "题目描述"); writer.addHeaderAlias("src", "学生代码"); writer.addHeaderAlias("score", "成绩");
result.add(ExcelSubmitModel.builder().score(Double.valueOf(examInfo.getExaminationScore())).build()); List<ExcelSubmitModel> rows = CollUtil.newArrayList(result); writer.write(rows, true); writer.flush(byteArrayInputStream, true); writer.close();
|
首先,先声明一个ByteArrayOutputStream流,ExcelWriter是hutools中对Excel poi的封装,
writer.addHeaderAlias(“”,””)是添加JavaBean类中的字段和Excel中文标题的对应关系。
ExcelWriter支持将List写入Excel,writer.write(row,true)完成对Excel的写入,
writer.flush(byteArrayInputStream,true);可以将Excel写入ByteArrayOutputStream流,
writer.close() 关闭流。
part2 . 封装的zipUtil类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| public class ZipUtil { public static ByteArrayOutputStream zip(HashMap<String, ByteArrayOutputStream> files, File tar) { try { ByteArrayOutputStream fileOutputStream = new ByteArrayOutputStream(); ZipOutputStream zipOutputStream = new ZipOutputStream(fileOutputStream); Iterator maplist = files.entrySet().iterator(); while (maplist.hasNext()) { Map.Entry<String, ByteArrayOutputStream> entry = (Map.Entry<String, ByteArrayOutputStream>) maplist.next(); ZipEntry zipEntry = new ZipEntry(entry.getKey()); zipOutputStream.putNextEntry(zipEntry); zipOutputStream.write(entry.getValue().toByteArray());
} zipOutputStream.close(); fileOutputStream.close(); return fileOutputStream; } catch (Exception e) { e.printStackTrace(); } return null;
} }
|
这个方法类,是接收一个HashMap<String,ByteArrayOutputStream>(Excel文件名,字节流),返回ByteArrayOutputStream 以便下一步的操作处理;
part3.将压缩后的字节流通过浏览器的response返回
1 2 3 4 5
| ByteArrayOutputStream zip = ZipUtil.zip(excel, new File("d://test8.zip"));
response.setHeader("Content-Disposition", "attachment;filename="+ URLEncoder.encode( examDesc + "_学生提交记录.zip","utf-8")); response.setContentType("application/zip"); response.getOutputStream().write(zip.toByteArray());
|
note
1、需要注意的部分是 如果返回的文件名中有中文,则需要 在resonse.setHeader()中,通过UrlEncoder.encode()来说明编码类型为utf-8
2、response可以接收的参数为 ByteArray;
3、整体思路 将文件转为ByteArrayOutputStream—>将ByteArrayOutputStream —>zipEntry—->zipzipOutputStream —>ByteArrayOutputStream—->byte[]