| ¶Ô±ÈÐÂÎļþ |
| | |
| | | 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; |
| | | } |
| | | } |
| | | |
| | | } |