1. 程式人生 > >POI java 處理excel上傳圖片

POI java 處理excel上傳圖片

在最近的專案開發中,遇到這樣一個需求,使用者匯入帶圖片的excel,excel批量匯入功能已做過很多了,帶圖片的是第一次嘗試,大概的要求有以下幾點:

  1. 所有excel中的圖片不能超出單元格,即必須在單元格內
  2. 所有圖片單個大小必須在1M以內
  3. 其中一列的單元格放入的圖片不能多於5張
  4. 其中一列的單元格為無限數量的圖片與不多於2000的字元

核心思路:獲取所有的圖片放入Map

  /**
     * 獲取Excel2003圖片
     *
     * @param sheet 當前sheet物件
     * @param workbook 工作簿物件
     * @return Map key:圖片左上角-右下角單元格索引+uuid(leftRow,leftCol_rightRow,rightCol_uuid)String,value:圖片流PictureData
     */
private Map<String, PictureData> getSheetPictrues03(HSSFSheet sheet, HSSFWorkbook workbook) { Map<String, PictureData> sheetIndexPicMap = new HashMap<String, PictureData>(); // 獲取excel上所有的圖片 List<HSSFPictureData> pictures = workbook.getAllPictures(); if
(pictures.size() != 0) { HSSFPatriarch hp = sheet.getDrawingPatriarch(); List<HSSFShape> shapeList = hp.getChildren(); for (HSSFShape shape : shapeList) { HSSFClientAnchor anchor = (HSSFClientAnchor) shape.getAnchor(); if (shape instanceof
HSSFPicture) { HSSFPicture pic = (HSSFPicture) shape; int pictureIndex = pic.getPictureIndex() - 1; HSSFPictureData picData = pictures.get(pictureIndex); String picIndex = String.valueOf(anchor.getRow1()) + "," + String.valueOf(anchor.getCol1()) + "_" + anchor.getRow2() + "," + String.valueOf(anchor.getCol2()) + "_" + UUID.randomUUID(); // Map key:圖片左上角-右下角單元格索引+uuid(1,2_3,4_uuid),左上右下定位一張圖片 // leftRow,leftCol_rightRow,rightCol_uuid ,放入返回的Map時,拼接uuid標示唯一的圖片 sheetIndexPicMap.put(picIndex, picData); } } } return sheetIndexPicMap; }

驗證關鍵程式碼

// 宣告的存放同一單元的圖片,方便後面判斷同一單元格圖片是否超過5張
   Map<String, String> numTempMap = new HashMap<String, String>();
            Object key[] = sheetIndexPicMap.keySet().toArray();
            for (int i = 0; i < sheetIndexPicMap.size(); i++) {
                String keyTemp = key[i].toString();

                // 圖片左上角所在的行列
                String leftTop = keyTemp.substring(0, keyTemp.indexOf("_"));
                // 圖片右下角所在的行列
                String rightBottom = keyTemp.substring(keyTemp.indexOf("_") + 1, keyTemp.lastIndexOf("_"));

                int leftRow = Integer.parseInt(leftTop.substring(0, leftTop.indexOf(",")));
                int leftCol = Integer.parseInt(leftTop.substring(leftTop.indexOf(",") + 1));

                int rightRow = Integer.parseInt(rightBottom.substring(0, rightBottom.indexOf(",")));
                int rightCol = Integer.parseInt(rightBottom.substring(rightBottom.indexOf(",") + 1));

                int currentCol = leftCol;
                int currentRow = leftRow;

                // 左上角行與右下角行不相同 或 左上角列與右下角列不相同,即為圖片超出單元格
                if (leftRow != rightRow || leftCol != rightCol) {
                    throw bizExceptions.create(CatalogError.ERROR_10001610, "圖片超出單元格!");
                }

                // 為使邏輯更清晰,分開兩種寫超出單元格的判斷,圖片不在4、5列的也為超出單元格
                // 這裡我的實際需求是,只有第4、5列才能上傳圖片
                if (!(leftCol == 4 || leftCol == 5)) {
                    throw bizExceptions.create(CatalogError.ERROR_10001610, "圖片超出單元格!");
                }


                PictureData pic = sheetIndexPicMap.get(key[i]);
                byte[] data = pic.getData();
                if (data.length / 1024.0 / 1024.0 > 3) {
                    throw bizExceptions.create(CatalogError.ERROR_10001608, "推薦描述圖片大小超過3M!");
                }

             // 這裡迴圈所有的圖片,同一單元的圖片放入同一key的Map中,後續根據判斷單元格的數量
                    if (!numTempMap.containsKey(currentRow + "")) {
                        for (int k = 0; k < sheetIndexPicMap.size(); k++) {
                            String keyTempk = key[k].toString();
                            String leftTopk = keyTempk.substring(0, keyTempk.indexOf("_"));
                            int currentRowk = Integer.parseInt(leftTopk.substring(0, leftTopk.indexOf(",")));
                            int currentColk = Integer.parseInt(leftTopk.substring(leftTopk.indexOf(",") + 1));

                            if (currentRow == currentRowk && currentColk == startCellNum) {
                                String productImgNumStr = numTempMap.get(currentRow + "");
                                int productImgNum = 0;
                                if (null != productImgNumStr) {
                                    productImgNum = Integer.parseInt(productImgNumStr) + 1;
                                }
                                numTempMap.put(currentRow + "", productImgNum + "");
                            }
                        }
                    }
                }
            }
            Object keyNum[] = numTempMap.keySet().toArray();
            for (int i = 0; i < numTempMap.size(); i++) {
                String productImgs = numTempMap.get(keyNum[i]);
                if (null != productImgs && Integer.parseInt(productImgs) >= 5) {
                    throw bizExceptions.create(CatalogError.ERROR_10001609, "產品圖片數量超過5張!");
                }
            }

這種方式,個人覺得還是有點太消耗效能,本來就是批量匯入,一次性將所有圖片放入Map中,然後迴圈key,實際處理中應該是很慢的,筆者供職外包,無法檢視線上實際情況。………….