1. 程式人生 > >web端多個excel的生成和打包成zip檔案

web端多個excel的生成和打包成zip檔案

需求
伺服器生成資料,但是資料超過一定行需要分成多個excel,並且打包成zip供web端下載。
分析

  1. 已知:
    1. 可以生成excel檔案
    2. 無法生成zip檔案包
  2. 需要做的事情
    1. 實現多個檔案的打包,生成zip檔案。
    2. 從一個excel檔案直接生成到生成多個檔案。
    3. 未知問題需要解決

流程

 public static void example2() throws IOException {
        //檔案流的目的,這裡可以用outpuStream快取
        File file = new File("D:\\f.zip");
        FileOutputStream fos = new
FileOutputStream(file); //指定zip流的輸出目的點 ZipOutputStream zip = new ZipOutputStream(fos); //包增加一個檔案條目,初始化輸入名稱 ZipEntry entry = new ZipEntry("test.txt"); zip.putNextEntry(entry); //輸入位元組流作為檔案條目的來源 zip.write("a simple txt".getBytes()); //同上 ZipEntry entry2 = new
ZipEntry("test2.txt"); zip.putNextEntry(entry2); zip.write("a simple file2".getBytes()); //關閉檔案條目的輸入點 zip.closeEntry(); //關閉zip流 zip.close(); }

main 函式如下

    public static void main(String[] args) {
        try {
            example2();
            System.out
.println("succeed!"); } catch (IOException e) { e.printStackTrace(); } }

外加條件:已經可以在web端生成了excel檔案,方法函式如下:

public ResponseEntity<byte[]> downloadInvoiceAndPackingList(@PathVariable("shipmentId") @NotNull Long shipmentId) {
        String filename = "xxxx.xlsx";
        String suffix = ".xlsx";
        StringBuilder downloadFileName = new StringBuilder("xxxx");
        try (InputStream input = EnvUtils.isDevFromSystem() ?     //模板輸入流
                this.getClass().getClassLoader().getResourceAsStream(
                        WmsConstant.WMS_TEMPLATE_ROOT + filename) :
                new FileInputStream(WmsPathUtil.getTemplateReportPath().resolve(filename).toFile());
                //結果輸出流
             ByteArrayOutputStream output = new ByteArrayOutputStream()) {
            Context context = new Context();
             //*******業務程式碼
             //jxlsHelper渲染處理xlxs,input+ context ---->outPut
            JxlsHelper.getInstance().processTemplate(input, output, context);
            //返回請求為位元組流
            return genResponseEntityFromBytes(MediaType.APPLICATION_OCTET_STREAM,
                    downloadFileName.toString(), output.toByteArray());
        } catch (Exception e) {
            throw new CodeException(CodeConstant.Common.DOWNLOAD_FILE_ERROR, e);
        }
    }

我們已知過程中有excel的輸出流生成,返回web段的是處理後輸出流生成的位元組流。

可能存在的方案
根據 1. 解決2.1 打包問題 我們有如下解決方案:

  1. 在伺服器生成快取資料夾,把excel先生成放在資料夾下
  2. 讀取路徑下的所有的excel檔案生成zip檔案流
  3. zip流生成位元組流返回到web端

這是一個解決方案,但這個方案有點小傻,做了太多的多餘事情。在結合外加條件,可以知道在生成現有excel的過程中,我們已經有檔案流生成了,那麼我們可以直接把生成的流,載入到zipOutputStream流中就可以了

          //這是zos的輸出流
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            ZipOutputStream zos = new ZipOutputStream(bos);
          //迴圈
            for (xxx:xxxxx) {
                 //****業務程式碼
                //定義檔案的輸入流
                InputStream input = EnvUtils.isDevFromSystem() ?
                        this.getClass().getClassLoader().getResourceAsStream(
                                WmsConstant.WMS_TEMPLATE_ROOT + filename) :
                        new FileInputStream(WmsPathUtil.getTemplateReportPath().resolve(filename).toFile());
                //定義檔案的輸出流,但是這是作為zip流的一部分
                ByteArrayOutputStream output = new ByteArrayOutputStream();
                //用jxlsHelper來處理xlxs輸出了流
                JxlsHelper jxlsHelper = new WmsJxlsHelper();
                jxlsHelper.processTemplate(input, output, context);
                //命名檔案
                zos.putNextEntry(new ZipEntry(channelName + ".xlsx"));
                //把xlxs輸出流作為輸入流輸入到zip輸出流中
                zos.write(output.toByteArray());
                zos.closeEntry();
                output.close();
            }
            //關閉zos,但是outputStream流依然存在記憶體中
            zos.close();
            return genResponseEntityFromBytes(MediaType.APPLICATION_OCTET_STREAM,
                    downloadFileName, bos.toByteArray());