From 8676f4cb37ef31fa9fcfe2a7faf5f4c4ea77cc1a Mon Sep 17 00:00:00 2001
From: MrShi <1878285526@qq.com>
Date: 星期四, 29 一月 2026 09:46:05 +0800
Subject: [PATCH] Merge branch 'master' of http://139.186.142.91:10010/r/productDev/zbom_dianjiang

---
 server/services/src/main/java/com/doumee/core/annotation/excel/ExcelPictureUtil.java |  309 +++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 309 insertions(+), 0 deletions(-)

diff --git a/server/services/src/main/java/com/doumee/core/annotation/excel/ExcelPictureUtil.java b/server/services/src/main/java/com/doumee/core/annotation/excel/ExcelPictureUtil.java
new file mode 100644
index 0000000..de3c552
--- /dev/null
+++ b/server/services/src/main/java/com/doumee/core/annotation/excel/ExcelPictureUtil.java
@@ -0,0 +1,309 @@
+package com.doumee.core.annotation.excel;
+import cn.hutool.json.JSONArray;
+import cn.hutool.json.JSONObject;
+import cn.hutool.json.XML;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.collections4.map.HashedMap;
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.poi.openxml4j.opc.PackagePartName;
+import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.usermodel.Workbook;
+import org.apache.poi.ss.usermodel.WorkbookFactory;
+import org.apache.poi.xssf.usermodel.*;
+
+import java.io.*;
+import java.nio.charset.StandardCharsets;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipInputStream;
+
+
+/**
+ * @author bianhl
+ * @version 1.0
+ * @description 鑾峰彇鍥剧墖璧勬簮
+ * @date 2024骞�4鏈�28鏃�08:44:42
+ */
+@Slf4j
+public class ExcelPictureUtil {
+
+    public static Map<String, XSSFPictureData> getExcelPictures(InputStream is) {
+        try {
+            byte[] fileData =  getFileStream(is);
+            Map<String, XSSFPictureData> pictures = getPictures(fileData);
+            pictures.forEach((id, xssfPictureData) -> {
+                System.out.println("id锛�" + id);
+                String fileName = xssfPictureData.getPackagePart().getPartName().getName();
+                System.out.println("fileName锛�" + fileName);
+            });
+            return pictures;
+        }catch (Exception e){
+            return  null;
+        }
+
+    }
+
+    /**
+     * 鑾峰彇娴姩鍥剧墖锛屼互 map 褰㈠紡杩斿洖锛岄敭涓鸿鍒楁牸寮� x-y銆�
+     *
+     * @param xssfSheet WPS 宸ヤ綔琛�
+     * @return 娴姩鍥剧墖鐨� map
+     */
+    public static Map<String, XSSFPictureData> getFloatingPictures(XSSFSheet xssfSheet) {
+        Map<String, XSSFPictureData> mapFloatingPictures = new HashMap<>();
+        XSSFDrawing drawingPatriarch = xssfSheet.getDrawingPatriarch();
+        if (drawingPatriarch != null) {
+            List<XSSFShape> shapes = drawingPatriarch.getShapes();
+            for (XSSFShape shape : shapes) {
+                if (shape instanceof XSSFPicture ) {
+                    XSSFPicture picture = (XSSFPicture)shape;
+                    XSSFClientAnchor anchor = (XSSFClientAnchor) picture.getAnchor();
+                    XSSFPictureData pictureData = picture.getPictureData();
+                    String key = anchor.getRow1() + "-" + anchor.getCol1();
+                    mapFloatingPictures.put(key, pictureData);
+                }
+            }
+        }
+        return mapFloatingPictures;
+    }
+
+    /**
+     * 澶勭悊 WPS 鏂囦欢涓殑鍥剧墖鏁版嵁锛岃繑鍥炲浘鐗囦俊鎭� map銆�
+     *
+     * @param stream    杈撳叆娴�
+     * @param mapConfig 閰嶇疆鏄犲皠
+     * @return 鍥剧墖淇℃伅鐨� map
+     * @throws IOException
+     */
+    private static Map<String, XSSFPictureData> processPictures(ByteArrayInputStream stream, Map<String, String> mapConfig) throws IOException {
+        Map<String, XSSFPictureData> mapPictures = new HashedMap<>();
+        Workbook workbook = WorkbookFactory.create(stream);
+        List<XSSFPictureData> allPictures = (List<XSSFPictureData>) workbook.getAllPictures();
+        for (XSSFPictureData pictureData : allPictures) {
+            PackagePartName partName = pictureData.getPackagePart().getPartName();
+            String uri = partName.getURI().toString();
+            if (mapConfig.containsKey(uri)) {
+                String strId = mapConfig.get(uri);
+                mapPictures.put(strId, pictureData);
+            }
+        }
+        return mapPictures;
+    }
+
+    /**
+     * 鑾峰彇 WPS 鏂囨。涓殑鍥剧墖锛屽寘鎷祵鍏ュ紡鍥剧墖鍜屾诞鍔ㄥ紡鍥剧墖銆�
+     *
+     * @param data 浜岃繘鍒舵暟鎹�
+     * @return 鍥剧墖淇℃伅鐨� map
+     * @throws IOException
+     */
+    public static Map<String, XSSFPictureData> getPictures(byte[] data) {
+        try {
+            Map<String, String> mapConfig = processZipEntries(new ByteArrayInputStream(data));
+            Map<String, XSSFPictureData> mapPictures = processPictures(new ByteArrayInputStream(data), mapConfig);
+            Iterator<Sheet> sheetIterator = WorkbookFactory.create(new ByteArrayInputStream(data)).sheetIterator();
+            while (sheetIterator.hasNext()) {
+                mapPictures.putAll(getFloatingPictures((XSSFSheet) sheetIterator.next()));
+            }
+            return mapPictures;
+        } catch (IOException e) {
+            return new HashedMap<>();
+        }
+    }
+
+    /**
+     * 澶勭悊 Zip 鏂囦欢涓殑鏉$洰锛屾洿鏂板浘鐗囬厤缃俊鎭��
+     *
+     * @param stream Zip 杈撳叆娴�
+     * @return 閰嶇疆淇℃伅鐨� map
+     * @throws IOException
+     */
+    private static Map<String, String> processZipEntries(ByteArrayInputStream stream) throws IOException {
+        Map<String, String> mapConfig = new HashedMap<>();
+        ZipInputStream zipInputStream = new ZipInputStream(stream);
+        ZipEntry zipEntry;
+        while ((zipEntry = zipInputStream.getNextEntry()) != null) {
+            try {
+                final String fileName = zipEntry.getName();
+                if ("xl/cellimages.xml".equals(fileName)) {
+                    processCellImages(zipInputStream, mapConfig);
+                } else if ("xl/_rels/cellimages.xml.rels".equals(fileName)) {
+                    return processCellImagesRels(zipInputStream, mapConfig);
+                }
+            } finally {
+                zipInputStream.closeEntry();
+            }
+        }
+        return new HashedMap<>();
+    }
+
+    /**
+     * 澶勭悊 Zip 鏂囦欢涓殑 cellimages.xml 鏂囦欢锛屾洿鏂板浘鐗囬厤缃俊鎭��
+     *
+     * @param zipInputStream Zip 杈撳叆娴�
+     * @param mapConfig      閰嶇疆淇℃伅鐨� map
+     * @throws IOException
+     */
+    private static void processCellImages(ZipInputStream zipInputStream, Map<String, String> mapConfig) throws IOException {
+        String content = IOUtils.toString(zipInputStream);
+        JSONObject jsonObject = XML.toJSONObject(content);
+        if (jsonObject != null) {
+            JSONObject cellImages = jsonObject.getJSONObject("etc:cellImages");
+            if (cellImages != null) {
+                JSONArray cellImageArray = null;
+                Object cellImage = cellImages.get("etc:cellImage");
+                if (cellImage != null && cellImage instanceof JSONArray) {
+                    cellImageArray = (JSONArray) cellImage;
+                } else if (cellImage != null && cellImage instanceof JSONObject) {
+                    JSONObject cellImageObj = (JSONObject) cellImage;
+                    if (cellImageObj != null) {
+                        cellImageArray = new JSONArray();
+                        cellImageArray.add(cellImageObj);
+                    }
+                }
+                if (cellImageArray != null) {
+                    processImageItems(cellImageArray, mapConfig);
+                }
+            }
+        }
+    }
+
+    /**
+     * 澶勭悊 cellImageArray 涓殑鍥剧墖椤癸紝鏇存柊鍥剧墖閰嶇疆淇℃伅銆�
+     *
+     * @param cellImageArray 鍥剧墖椤圭殑 JSONArray
+     * @param mapConfig      閰嶇疆淇℃伅鐨� map
+     */
+    private static  void processImageItems(JSONArray cellImageArray, Map<String, String> mapConfig) {
+        for (int i = 0; i < cellImageArray.size(); i++) {
+            JSONObject imageItem = cellImageArray.getJSONObject(i);
+            if (imageItem != null) {
+                JSONObject pic = imageItem.getJSONObject("xdr:pic");
+                if (pic != null) {
+                    processPic(pic, mapConfig);
+                }
+            }
+        }
+    }
+
+    /**
+     * 澶勭悊 pic 涓殑鍥剧墖淇℃伅锛屾洿鏂板浘鐗囬厤缃俊鎭��
+     *
+     * @param pic       鍥剧墖鐨� JSONObject
+     * @param mapConfig 閰嶇疆淇℃伅鐨� map
+     */
+    private static  void processPic(JSONObject pic, Map<String, String> mapConfig) {
+        JSONObject nvPicPr = pic.getJSONObject("xdr:nvPicPr");
+        if (nvPicPr != null) {
+            JSONObject cNvPr = nvPicPr.getJSONObject("xdr:cNvPr");
+            if (cNvPr != null) {
+                String name = cNvPr.getStr("name");
+                if (StringUtils.isNotEmpty(name)) {
+                    String strImageEmbed = updateImageEmbed(pic);
+                    if (strImageEmbed != null) {
+                        mapConfig.put(strImageEmbed, name);
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * 鑾峰彇宓屽叆寮忓浘鐗囩殑 embed 淇℃伅銆�
+     *
+     * @param pic 鍥剧墖鐨� JSONObject
+     * @return embed 淇℃伅
+     */
+    private  static String updateImageEmbed(JSONObject pic) {
+        JSONObject blipFill = pic.getJSONObject("xdr:blipFill");
+        if (blipFill != null) {
+            JSONObject blip = blipFill.getJSONObject("a:blip");
+            if (blip != null) {
+                return blip.getStr("r:embed");
+            }
+        }
+        return null;
+    }
+
+    /**
+     * 澶勭悊 Zip 鏂囦欢涓殑 relationship 鏉$洰锛屾洿鏂伴厤缃俊鎭��
+     *
+     * @param zipInputStream Zip 杈撳叆娴�
+     * @param mapConfig      閰嶇疆淇℃伅鐨� map
+     * @return 閰嶇疆淇℃伅鐨� map
+     * @throws IOException
+     */
+    private static Map<String, String> processCellImagesRels(ZipInputStream zipInputStream, Map<String, String> mapConfig) throws IOException {
+        String content = IOUtils.toString(zipInputStream );
+        JSONObject jsonObject = XML.toJSONObject(content);
+        JSONObject relationships = jsonObject.getJSONObject("Relationships");
+        if (relationships != null) {
+            JSONArray relationshipArray = null;
+            Object relationship = relationships.get("Relationship");
+
+            if (relationship != null && relationship instanceof JSONArray) {
+                relationshipArray = (JSONArray) relationship;
+            } else if (relationship != null && relationship instanceof JSONObject  ) {
+                JSONObject relationshipObj = (JSONObject) relationship;
+                if (relationshipObj != null) {
+                    relationshipArray = new JSONArray();
+                    relationshipArray.add(relationshipObj);
+                }
+            }
+            if (relationshipArray != null) {
+                return processRelationships(relationshipArray, mapConfig);
+            }
+        }
+        return null;
+    }
+
+    /**
+     * 澶勭悊 relationshipArray 涓殑鍏崇郴椤癸紝鏇存柊閰嶇疆淇℃伅銆�
+     *
+     * @param relationshipArray 鍏崇郴椤圭殑 JSONArray
+     * @param mapConfig         閰嶇疆淇℃伅鐨� map
+     * @return 閰嶇疆淇℃伅鐨� map
+     */
+    private static Map<String, String> processRelationships(JSONArray relationshipArray, Map<String, String> mapConfig) {
+        Map<String, String> mapRelationships = new HashedMap<>();
+        for (int i = 0; i < relationshipArray.size(); i++) {
+            JSONObject relaItem = relationshipArray.getJSONObject(i);
+            if (relaItem != null) {
+                String id = relaItem.getStr("Id");
+                String value = "/xl/" + relaItem.getStr("Target");
+                if (mapConfig.containsKey(id)) {
+                    String strImageId = mapConfig.get(id);
+                    mapRelationships.put(value, strImageId);
+                }
+            }
+        }
+        return mapRelationships;
+    }
+
+    /**
+     * @return {@link byte[]}
+     * @description
+     * @author bianhl
+     * @date 2024/4/26 13:52
+     */
+    private static byte[] getFileStream(InputStream inputStream) {
+            // 鍒涘缓 ByteArrayOutputStream 鏉ユ殏瀛樻祦鏁版嵁
+        try {
+            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
+            byte[] buffer = new byte[1024];
+            int length;
+            while ((length = inputStream.read(buffer)) != -1) {
+                byteArrayOutputStream.write(buffer, 0, length);
+            }
+            // 灏� byteArrayOutputStream 鐨勫唴瀹硅幏鍙栦负瀛楄妭鏁扮粍
+            return byteArrayOutputStream.toByteArray();
+        } catch (IOException e) {
+            return null;
+        }
+    }
+
+}
\ No newline at end of file

--
Gitblit v1.9.3