HOME/Articles/

内存中将Excel打包成Zip

Article Outline

需求分析

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 并转成字节流
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<JavaBean>写入Excel,writer.write(row,true)完成对Excel的写入,

writer.flush(byteArrayInputStream,true);可以将Excel写入ByteArrayOutputStream流,

writer.close() 关闭流。

part2 . 封装的zipUtil类
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返回
  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[]