1. 程式人生 > >Java實現匯出多個excel表打包到zip檔案中->供客戶端下載

Java實現匯出多個excel表打包到zip檔案中->供客戶端下載

業務需求:將需求方要的資料匯出excel表中。

                1.只發出一次請求

                 2.每個excel表中到資料記錄不能超過50條

碰過的坑:原先我發出的是ajax請求,然後請求成功卻返回的都是亂碼!我是想要下載檔案啊!!!

                 ajax請求,響應的是文字資料,所以下載檔案不能用ajax請求!用什麼呢?用連結就行了

  location.href= "../../aliGoodsOrder/export?startDate="+app.startDate+"&endDate="+app.endDate;

或者一個<a href=""></a> 標籤。

後臺怎麼匯出excel呢,分享一個特別簡單的工具類給大家:

@Log4j
public class Excel {

    public static HSSFWorkbook createExcel(String sheetName, List<String> cellNameList) {

        HSSFWorkbook excel = new HSSFWorkbook();
        HSSFSheet sheet = excel.createSheet(sheetName);
        HSSFRow row = sheet.createRow(0);
        int cellIndex = 0;
        for (String cellName : cellNameList) {
            HSSFCell cell = row.createCell(cellIndex);
            cell.setCellValue(cellName);
            cellIndex++;
        }
        return excel;
    }

    public static HSSFWorkbook createExcelData(HSSFWorkbook excel, List<String> excelData,int rowIndex ,int columnSum){
        HSSFRow row=excel.getSheetAt(0).createRow(rowIndex);
        for(int i = 0; i < columnSum; i++){
            row.createCell(i).setCellValue(excelData.get(i));
        }
        return excel;
    }

}
  <!-- https://mvnrepository.com/artifact/org.apache.poi/poi-ooxml -->
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
            <version>3.16</version>
        </dependency>

 

怎麼使用呢:


    /**
     * @ Date       :2018/11/05
     * @ Description:將1688商品訂單匯出Excel
     */
    private HSSFWorkbook exportExcel(List<AliGoodsOrder> allList,String name){
        log.info("|createdExcel================start!============|");
        HSSFWorkbook excel = null;
        try{
            List<String> cellNameList = new ArrayList<>();
            cellNameList.add("訂單號");
            cellNameList.add("商品名稱");
            cellNameList.add("商品數量(件)");
            cellNameList.add("商品規格1(如:顏色)");
            cellNameList.add("商品規格2(如:尺碼)");
            cellNameList.add("收件人-姓名");
            cellNameList.add("收件人-手機");
            cellNameList.add("收件人-省");
            cellNameList.add("收件人-市");
            cellNameList.add("收件人-區");
            cellNameList.add("收件人-詳細地址");
            cellNameList.add("買家留言");
            cellNameList.add("1688商品id");
            String fileName = name;
            String sheetName  = name;
            excel = Excel.createExcel(sheetName,cellNameList);

            int rowIndex = 1;
            for (AliGoodsOrder order:
                    allList ) {
                List<String> excelDate = new ArrayList<>();
                excelDate.add("");//訂單號設定為空
                excelDate.add(order.getTitle()+"");
                excelDate.add(order.getNum()+"");
                excelDate.add(order.getSku1()+"");
                excelDate.add(order.getSku2()+"");
                excelDate.add(order.getReceiverName()+"");
                excelDate.add(order.getReceiverTel()+"");
                excelDate.add(order.getDeliveryProvince()+"");
                excelDate.add(order.getDeliveryCity()+"");
                excelDate.add(order.getDeliveryDistrict()+"");
                excelDate.add(order.getDeliveryAddress()+"");
                excelDate.add(order.getBuyerMessage()+"");
                excelDate.add(order.getAliId()+"");
                excel = Excel.createExcelData(excel,excelDate,rowIndex,13);
                rowIndex++;
            }

            log.info("|createdExcel================end!============|");
        }catch (Exception e){
            log.error(ExceptionUtils.getTraceInfo(e));
        }
        return excel;
    }

目前位置,excel的匯出完成了呢?想要客戶端下載的小寶貝們,可以把以下方法放入工具類中哦

    //匯出excel檔案
    public static  void downLoad(HttpServletResponse response, String fileName, HSSFWorkbook wb){
        try {
            response.reset();
            response.setContentType("application/ms-excel;charset=UTF-8");
            response.setHeader("Content-Disposition", "attachment;filename=".concat(String.valueOf(URLEncoder.encode(fileName+".xls", "UTF-8"))));
            try {
                wb.write(response.getOutputStream());
                response.getOutputStream().flush();
            } catch (Exception e) {
                log.error("Excel匯出出錯", e);
                throw e;
            }finally{
                if(response.getOutputStream()!=null){
                    response.getOutputStream().close();
                }
            }

        }catch (Exception e){
            log.error("downLoadExcel-------fail!");
            log.error(ExceptionUtils.getTraceInfo(e));
        }

    }

 如果你是需要客戶端請求下載一個excle檔案,到這裡就可以結束咯(ps只要在控制類中呼叫此類就完成了)

如果你是想要將多個excel表打包成zip後再下載,請繼續看

程式碼不必看懂!!!!你只要知道以下是為了獲取一個excel表的列表(這裡還有個小小知識點就是列表的子列表哦)

    /**
     * 分頁獲取Excel的list列表
     * @param startDate
     * @param endDate
     * @return
     */
    private List<HSSFWorkbook> getExcelByPagination(String startDate, String endDate){
        List<AliGoodsOrder> list = getOrderByDate(startDate,endDate);
        int totalPage = list.size()%50 == 0 ? list.size()/50 : list.size()/50 + 1;

        List<HSSFWorkbook> hssfWorkbookList = new ArrayList<>();
        String fileName = startDate+"至"+endDate+"1688商品貨單資訊";
        for(int page = 1; page <= totalPage; page++){

            int fromIndex = (page-1)*50;
            int toIndex;
            if(page == totalPage && list.size()%50!= 0){
                toIndex = fromIndex + list.size()%50;
            }else{
                toIndex = fromIndex + 50;
            }

            HSSFWorkbook hssfWorkbook = exportExcel(list.subList(fromIndex,toIndex),fileName);
            if(hssfWorkbook != null){
                hssfWorkbookList.add(hssfWorkbook);
            }

        }
        return hssfWorkbookList;
    }

下載zip的工具類要貼出來了~

    //直接下載
    public static void downFileByStream(HttpServletResponse response,List<HSSFWorkbook> excels,String fileName){
        try {
            OutputStream toClient = new BufferedOutputStream(response.getOutputStream());
            ZipOutputStream zipOut = new ZipOutputStream(toClient);
            for(int i=0;i<excels.size();i++){
                ZipEntry entry = new ZipEntry(fileName+i+".xls");
                zipOut.putNextEntry(entry);
                excels.get(i).write(zipOut);
            }
            zipOut.flush();
            zipOut.close();
        }catch (Exception e){
            log.error("downFileByStream==========fail");
            log.error(ExceptionUtils.getTraceInfo(e));
        }
    }

用法---》下載的實現服務類

    /**
     * @ Date       :2018/11/05
     * @ Description:一個excel表中匯出50條記錄,打包放入zip檔案中並下載
     */
    @Override
    public void downLoadZip(HttpServletResponse response,String startDate, String endDate) {
        try {
            List<HSSFWorkbook> hssfWorkbookList = getExcelByPagination(startDate,endDate);
            String fileName = startDate+"至"+endDate+"1688商品貨單資訊";

//            File temp = File.createTempFile("temp",".zip");
//            FileUtil.zipFiles(hssfWorkbookList,temp,fileName);
//            response = FileUtil.downFile(response, temp);
//            temp.deleteOnExit();
            FileUtil.downFileByStream(response,hssfWorkbookList,fileName);
        }catch (Exception e){
            log.error("downLoadZip=======fail!"+ExceptionUtils.getTraceInfo(e));

        }

    }

 從前端至後臺的程式碼就貼完了

為啥上面程式碼有幾行程式碼註釋了呢?因為之前的想法是將excel匯出後打包為zip檔案,然後客戶端就可以請求檔案下載了。

但是之後發現多此一舉了,直接將檔案流存到response.getOutputStream()裡面就行了

也貼下這個冗餘的程式碼把。

   /**
     * 將多個Excel打包成zip檔案
     * @param srcfile
     * @param zipfile
     */
    public static void zipFiles(List<HSSFWorkbook> srcfile, File zipfile,String fileName) {
        try {
            ZipOutputStream out = new ZipOutputStream(new FileOutputStream(zipfile));
            for (int i = 0; i < srcfile.size(); i++) {
                out.putNextEntry(new ZipEntry(fileName+i+".xls"));
                srcfile.get(i).write(out);
            }
            out.flush();
            out.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    /**
     * 下載檔案
     * @param response
     * @param file
     * @return
     */
    public static HttpServletResponse downFile(HttpServletResponse response, File file) {
        try {
            // 以流的形式下載檔案。
            InputStream fis = new BufferedInputStream(new FileInputStream(file.getPath()));
            byte[] buffer = new byte[fis.available()];
            fis.read(buffer);
            fis.close();
            // 清空response
            response.reset();
            OutputStream toClient = new BufferedOutputStream(response.getOutputStream());
            response.setContentType("application/x-zip-compressed");
            response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(file.getName(), "UTF-8"));
            toClient.write(buffer);
            toClient.flush();
            toClient.close();
        } catch (IOException ex) {
            ex.printStackTrace();
        }
        return null;
    }

看到這個下載檔案的程式碼,我又要多叨嘮一句了,為啥我最後又是返回的null呢?因為返回response報錯了呀,看網上大家都說

response.getOutputStream()和伺服器裡的out.write()衝突了啥啥啥反正我是沒看懂,只記住了一個可愛的小朋友說,你只要返回null就行了。。。

這篇部落格就這樣粗略的貼程式碼放功能把,下篇了再講講遇到的新知識點