当前位置: 首页 > news >正文

jeecg导入excel 含图片(嵌入式,浮动式)

jeecgboot的excel导入 含图片(嵌入式,浮动式)

  • 一、啰嗦
  • 二、准备
  • 三、 代码
    • 1、代码(修改覆写的ExcelImportServer)
    • 2、代码(修改覆写的PoiPublicUtil)
    • 3、代码(新增类SAXParserHandler)
    • 4、代码(PoiPublicUtil文件中加入convertPackagePartToPictureData方法)
  • 四、总结
    • 1、ExcelImportServer代码
    • 2、PoiPublicUtil代码
    • 3、SAXParserHandler代码

看流程可以往下看看,使用代码直接调到四、总结

一、啰嗦

不写公共用的了,就直接写出自己遇到的。
原本以为跟导入一样,就只是一个简单的导出,鬼知道在excel中加入图片有两种方式(嵌入式和浮动式)在这里插入图片描述
然而项目支持浮动式,可是当我使用浮动式插入图片时(没对比没伤害),他直接撑开了,下面这个还好,我还有一个直接占满我整个屏幕跟我壁纸一样了都,要是插入多了。光调节大小就得烦死了。 在这里插入图片描述
又得写代码,我一搜,文档没有,框架相关的文章也没有,只能自己写,我这个cv工程师直接崩溃(得亏还有ChatGPT,项目需要,直接拼拼凑凑开始干叭)
在这里插入图片描述

二、准备

说是准备其实也没啥,就是啰嗦+1了
目前excel的版本有两种Excel 2003 的.xlsExcel 2007 .xls.xlsx,也不知道说的标准不标准
这里使用的就是Excel 2007这个版本的,因为03版的还没有方法访问内置文件,07的可以进行访问(能访问也就能获取到其中的图片,也可能是我技术不到,反正我得问AI,还是简单来)
具体需要导入的数据如下(反正都差不多,我怕在涉及一些数据,就随便改了改,反正主要是导入图片,不要在意这些细节了)
在这里插入图片描述

三、 代码

啰里啰嗦的终于要了代码环节了
在这里插入图片描述

具体导入在JeecgController类里的importExcel这个方法,复制出来修改为自己的就可以(都是大佬肯定嘎嘎简单)

具体使用的就是这个方法

List<T> list = ExcelImportUtil.importExcel(file.getInputStream(), clazz, params);

点击他会跳转到下面的方法

/*** Excel 导入 数据源IO流,不返回校验结果 导入 字段类型 Integer,Long,Double,Date,String,Boolean* * @param file* @param pojoClass* @param params* @return* @throws Exception*/
public static <T> List<T> importExcel(InputStream inputstream, Class<?> pojoClass, ImportParams params) throws Exception {return new ExcelImportServer().importExcelByIs(inputstream, pojoClass, params).getList();
}

然后再次点击又跳到下面这个方法

/*** Excel 导入 field 字段类型 Integer,Long,Double,Date,String,Boolean* * @param inputstream* @param pojoClass* @param params* @return* @throws Exception*/
public ExcelImportResult importExcelByIs(InputStream inputstream, Class<?> pojoClass, ImportParams params) throws Exception {if (LOGGER.isDebugEnabled()) {LOGGER.debug("Excel import start ,class is {}", pojoClass);}List<T> result = new ArrayList<T>();Workbook book = null;boolean isXSSFWorkbook = false;if (!(inputstream.markSupported())) {inputstream = new PushbackInputStream(inputstream, 8);}//begin-------author:liusq------date:20210129-----for:-------poi3升级到4兼容改造工作【重要敏感修改点】--------//------poi4.x begin----
//		FileMagic fm = FileMagic.valueOf(FileMagic.prepareToCheckMagic(inputstream));
//		if(FileMagic.OLE2 == fm){
//			isXSSFWorkbook=false;
//		}book = WorkbookFactory.create(inputstream);if(book instanceof XSSFWorkbook){isXSSFWorkbook=true;}LOGGER.info("  >>>  poi3升级到4.0兼容改造工作, isXSSFWorkbook = " +isXSSFWorkbook);//end-------author:liusq------date:20210129-----for:-------poi3升级到4兼容改造工作【重要敏感修改点】--------//begin-------author:liusq------date:20210313-----for:-------多sheet导入改造点--------//获取导入文本的sheet数//update-begin-author:taoyan date:20211210 for:https://gitee.com/jeecg/jeecg-boot/issues/I45C32 导入空白sheet报错if(params.getSheetNum()==0){int sheetNum = book.getNumberOfSheets();if(sheetNum>0){params.setSheetNum(sheetNum);}}//update-end-author:taoyan date:20211210 for:https://gitee.com/jeecg/jeecg-boot/issues/I45C32 导入空白sheet报错//end-------author:liusq------date:20210313-----for:-------多sheet导入改造点--------createErrorCellStyle(book);Map<String, PictureData> pictures;//update-begin-author:liusq date:20220609 for:issues/I57UPC excel导入 ImportParams 中没有startSheetIndex参数for (int i = params.getStartSheetIndex(); i < params.getStartSheetIndex()+ params.getSheetNum(); i++) {//update-end-author:liusq date:20220609 for:issues/I57UPC excel导入 ImportParams 中没有startSheetIndex参数if (LOGGER.isDebugEnabled()) {LOGGER.debug(" start to read excel by is ,startTime is {}", System.currentTimeMillis());}if (isXSSFWorkbook) {pictures = PoiPublicUtil.getSheetPictrues07((XSSFSheet) book.getSheetAt(i), (XSSFWorkbook) book);} else {pictures = PoiPublicUtil.getSheetPictrues03((HSSFSheet) book.getSheetAt(i), (HSSFWorkbook) book);}if (LOGGER.isDebugEnabled()) {LOGGER.debug(" end to read excel by is ,endTime is {}", new Date().getTime());}result.addAll(importExcel(result, book.getSheetAt(i), pojoClass, params, pictures));if (LOGGER.isDebugEnabled()) {LOGGER.debug(" end to read excel list by pos ,endTime is {}", new Date().getTime());}}if (params.isNeedSave()) {saveThisExcel(params, pojoClass, isXSSFWorkbook, book);}return new ExcelImportResult(result, verfiyFail, book);
}

1、代码(修改覆写的ExcelImportServer)

上面的importExcelByIs这个方法需要进行一些修改,但因为是源码包,无法进行修改,所以这时候就要把他复制出来,存放相同的地址,然后就完成替换了
包名为package org.jeecgframework.poi.excel.imports;下的ExcelImportServer文件
直接一顿cv完工
在这里插入图片描述

然后修改的代码如下(有可以导入嵌入式图片 又不能影响之前导入使用)
具体就是:
1、加入了OPCPackage 进行读取07版的excel的包
2、之前运行完book = WorkbookFactory.create(inputstream);会把输入流进行关闭,这里将输入流复制到字节数组ByteArrayOutputStream,然后在获取到OPCPackage 之后手动关闭流

/*** Excel 导入 field 字段类型 Integer,Long,Double,Date,String,Boolean** @param inputstream* @param pojoClass* @param params* @return* @throws Exception*/public ExcelImportResult importExcelByIs(InputStream inputstream, Class<?> pojoClass, ImportParams params) throws Exception {if (LOGGER.isDebugEnabled()) {LOGGER.debug("Excel import start ,class is {}", pojoClass);}List<T> result = new ArrayList<T>();Workbook book = null;OPCPackage opc = null;boolean isXSSFWorkbook = false;if (!(inputstream.markSupported())) {inputstream = new PushbackInputStream(inputstream, 8);}//begin-------author:liusq------date:20210129-----for:-------poi3升级到4兼容改造工作【重要敏感修改点】--------//------poi4.x begin----
//		FileMagic fm = FileMagic.valueOf(FileMagic.prepareToCheckMagic(inputstream));
//		if(FileMagic.OLE2 == fm){
//			isXSSFWorkbook=false;
//		}// 将输入流内容复制到字节数组ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();byte[] buffer = new byte[1024];int bytesRead;while ((bytesRead = inputstream.read(buffer)) != -1) {byteArrayOutputStream.write(buffer, 0, bytesRead);}byte[] workbookData = byteArrayOutputStream.toByteArray();try (ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(workbookData)) {// 创建Workbook,不会直接关闭原始输入流book = WorkbookFactory.create(byteArrayInputStream);if (book instanceof XSSFWorkbook) {isXSSFWorkbook = true;opc = PackageHelper.open(new ByteArrayInputStream(workbookData));}} finally {try {//之前操作自动关闭了输入流,由于输入流内容复制到字节数组没有进行关闭,所以这里进行关闭inputstream.close();} catch (IOException e) {LOGGER.info("Error closing input stream: " + e.getMessage());}}
//        book = WorkbookFactory.create(nonClosingInputStream);
//        if (book instanceof XSSFWorkbook) {
//            isXSSFWorkbook = true;
//            opc = PackageHelper.open(inputstream);
//        }LOGGER.info("  >>>  poi3升级到4.0兼容改造工作, isXSSFWorkbook = " + isXSSFWorkbook);//end-------author:liusq------date:20210129-----for:-------poi3升级到4兼容改造工作【重要敏感修改点】--------//begin-------author:liusq------date:20210313-----for:-------多sheet导入改造点--------//获取导入文本的sheet数//update-begin-author:taoyan date:20211210 for:https://gitee.com/jeecg/jeecg-boot/issues/I45C32 导入空白sheet报错if (params.getSheetNum() == 0) {int sheetNum = book.getNumberOfSheets();if (sheetNum > 0) {params.setSheetNum(sheetNum);}}//update-end-author:taoyan date:20211210 for:https://gitee.com/jeecg/jeecg-boot/issues/I45C32 导入空白sheet报错//end-------author:liusq------date:20210313-----for:-------多sheet导入改造点--------createErrorCellStyle(book);Map<String, PictureData> pictures;//update-begin-author:liusq date:20220609 for:issues/I57UPC excel导入 ImportParams 中没有startSheetIndex参数for (int i = params.getStartSheetIndex(); i < params.getStartSheetIndex()+ params.getSheetNum(); i++) {//update-end-author:liusq date:20220609 for:issues/I57UPC excel导入 ImportParams 中没有startSheetIndex参数if (LOGGER.isDebugEnabled()) {LOGGER.debug(" start to read excel by is ,startTime is {}", System.currentTimeMillis());}//03版xls因为文件限制暂时无法识别内嵌图片//07版xlsx 此处以进行适配内嵌图片,内嵌和浮动自动识别返回if (isXSSFWorkbook) {pictures = PoiPublicUtil.getAllPictures(opc,(XSSFSheet) book.getSheetAt(i), (XSSFWorkbook) book);
//                pictures = PoiPublicUtil.getSheetPictrues07((XSSFSheet) book.getSheetAt(i), (XSSFWorkbook) book);} else {pictures = PoiPublicUtil.getSheetPictrues03((HSSFSheet) book.getSheetAt(i), (HSSFWorkbook) book);}if (LOGGER.isDebugEnabled()) {LOGGER.debug(" end to read excel by is ,endTime is {}", new Date().getTime());}result.addAll(importExcel(result, book.getSheetAt(i), pojoClass, params, pictures));if (LOGGER.isDebugEnabled()) {LOGGER.debug(" end to read excel list by pos ,endTime is {}", new Date().getTime());}}if (params.isNeedSave()) {saveThisExcel(params, pojoClass, isXSSFWorkbook, book);}return new ExcelImportResult(result, verfiyFail, book);}

2、代码(修改覆写的PoiPublicUtil)

上述代码在这里使用方法进行识别图片,具体加入的方法是getAllPictures(OPCPackage opc, XSSFSheet sheet, XSSFWorkbook workbook)

//03版xls因为文件限制暂时无法识别内嵌图片//07版xlsx 此处以进行适配内嵌图片,内嵌和浮动自动识别返回if (isXSSFWorkbook) {pictures = PoiPublicUtil.getAllPictures(opc,(XSSFSheet) book.getSheetAt(i), (XSSFWorkbook) book);
//                pictures = PoiPublicUtil.getSheetPictrues07((XSSFSheet) book.getSheetAt(i), (XSSFWorkbook) book);} else {pictures = PoiPublicUtil.getSheetPictrues03((HSSFSheet) book.getSheetAt(i), (HSSFWorkbook) book);}

点击会getSheetPictrues03或getSheetPictrues07也调到源码路径
包名package org.jeecgframework.poi.util;下的PoiPublicUtil文件
这里模仿上面也复制出来一份
在这里插入图片描述

加入以下方法,浮动式调用的值自带的,嵌入式使用了一个手写的方法

public static Map<String, PictureData> getAllPictures(OPCPackage opc, XSSFSheet sheet, XSSFWorkbook workbook) throws Exception {Map<String, PictureData> sheetIndexPicMap = new HashMap<>();// 处理嵌入式图片List<PackagePart> parts = opc.getParts();sheetIndexPicMap.putAll(getEmbedPictures(parts));// 处理浮动式图片sheetIndexPicMap.putAll(getSheetPictrues07(sheet, workbook));return sheetIndexPicMap;}

getEmbedPictures方法

/*** 获取嵌入式图片* @param parts* @return* @throws JDOMException* @throws IOException* @throws ParserConfigurationException*/private static Map<String, PictureData> getEmbedPictures(List<PackagePart> parts) throws JDOMException, IOException, ParserConfigurationException, SAXException {Map<String, Set<String>> mapImg = new HashMap<>();Map<String, String> mapImgPath = new HashMap<>();Map<Integer, List<String>> dataMap = new HashMap<>();for (PackagePart part : parts) {
//            System.out.println(part.getPartName());PackagePartName partName = part.getPartName();String name = partName.getName();if ("/xl/cellimages.xml".equals(name)) {SAXBuilder builder = new SAXBuilder();// 获取文档Document doc = builder.build(part.getInputStream());// 获取根节点Element root = doc.getRootElement();List<Element> cellImageList = root.getChildren();for (Element imgEle : cellImageList) {Element xdrPic = imgEle.getChildren().get(0);Element xdrNvPicPr = xdrPic.getChildren().get(0);Element xdrBlipFill = xdrPic.getChildren().get(1);Element aBlip = xdrBlipFill.getChildren().get(0);Attribute attr = aBlip.getAttributes().get(0);String imgId = xdrNvPicPr.getChildren().get(0).getAttributeValue("name");String id = attr.getValue();if (mapImg.containsKey(id)) {mapImg.get(id).add(imgId);} else {Set<String> set = new HashSet<>();set.add(imgId);mapImg.put(id, set);}}}if ("/xl/_rels/cellimages.xml.rels".equals(name)) {SAXBuilder builder = new SAXBuilder();// 获取文档Document doc = builder.build(part.getInputStream());// 获取根节点Element root = doc.getRootElement();List<Element> relationshipList = root.getChildren();for (Element relationship : relationshipList) {String id = relationship.getAttributeValue("Id");String target = relationship.getAttributeValue("Target");mapImgPath.put(id, target);}}if (name.contains("/xl/worksheets/sheet")) {// 获取文档String sheetNoStr = name.replace("/xl/worksheets/sheet", "").replace(".xml", "");Integer sheetNo = Integer.valueOf(sheetNoStr) - 1;// 步骤1:创建SAXParserFactory实例SAXParserFactory factory = SAXParserFactory.newInstance();// 步骤2:创建SAXParser实例SAXParser saxParser = factory.newSAXParser();SAXParserHandler saxParserHandler = new SAXParserHandler();saxParser.parse(part.getInputStream(), saxParserHandler);List<String> rows = saxParserHandler.getRows();dataMap.put(sheetNo, rows);}}Map<String, String> imgMap = new HashMap<>();for (String id : mapImg.keySet()) {Set<String> imgIds = mapImg.get(id);String path = mapImgPath.get(id);for (String imgId : imgIds) {imgMap.put(imgId, path);}}for (Integer key : dataMap.keySet()) {List<String> rows = dataMap.get(key);for (int i = 0; i < rows.size(); i++) {String imgId = rows.get(i);String imgId_index = imgId.substring(0, imgId.indexOf(":"));String imgId_url = imgId.substring(imgId.indexOf(":")+1);if (imgMap.containsKey(imgId_url)) {rows.set(i, imgId_index+":"+imgMap.get(imgId_url));}}}Map<String, PictureData> map = new HashMap<>();for (Integer key : dataMap.keySet()) {List<String> pathList = dataMap.get(key);for (int i = 0; i < pathList.size(); i++) {String path = pathList.get(i);String path_index = path.substring(0, path.indexOf(":"));String path_url = path.substring(path.indexOf(":")+1);if (StringUtils.isNotEmpty(path_url)) {for (PackagePart part : parts) {PackagePartName partName = part.getPartName();String name = partName.getName();if (name.contains(path_url)) {//进行转换PictureData pictureData = convertPackagePartToPictureData(part,new XSSFWorkbook());map.put(path_index, pictureData);break;}}}}}return map;}

上面的方法
1、调用了一个xml解析的自定义类SAXParserHandler
2、调用了一个PackagePart转换为PictureData的方法convertPackagePartToPictureData

3、代码(新增类SAXParserHandler)

实体类SAXParserHandler,我跟上面一样也这样建了
在这里插入图片描述

package org.jeecgframework.poi.xml;import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;import java.util.ArrayList;
import java.util.List;//xml解析
public class SAXParserHandler extends DefaultHandler {String value = null;List<String> rows = new ArrayList<>();int rowIndex = 0;int currentColumn = 0;public List<String> getRows() {return rows;}//用来标识解析开始@Overridepublic void startDocument() throws SAXException {super.startDocument();}//用来标识解析结束@Overridepublic void endDocument() throws SAXException {super.endDocument();}//解析xml元素@Overridepublic void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {super.startElement(uri, localName, qName, attributes);if (qName.equals("row")) {value = "";// 遇到新的行时,重置列号为0currentColumn = 0;} else if (qName.equals("c")) {// 获取列号String columnRef = attributes.getValue("r");if (columnRef != null) {currentColumn = parseColumnIndex(columnRef.replaceAll("[^A-Z]", ""));}}}@Overridepublic void endElement(String uri, String localName, String qName) throws SAXException {super.endElement(uri, localName, qName);if (qName.equals("c")) {if (value != null && value.contains("DISPIMG")) {value = value.substring(value.lastIndexOf("DISPIMG(")).replace("DISPIMG(\"", "");value = value.substring(0, value.indexOf("\""));
//                rows.add(rowIndex, value);rows.add(rowIndex + "_" + currentColumn + ":" + value);} else {
//                rows.add(rowIndex, null);rows.add(rowIndex + "_" + currentColumn + ":null");}value = "";}else if (qName.equals("row")) {rowIndex++;}}@Overridepublic void characters(char[] ch, int start, int length) throws SAXException {super.characters(ch, start, length);value += new String(ch, start, length);}// 解析列号private int parseColumnIndex(String columnRef) {int result = 0;for (int i = 0; i < columnRef.length(); i++) {result = result * 26 + (columnRef.charAt(i) - 'A' + 1);}return result - 1;}
}

4、代码(PoiPublicUtil文件中加入convertPackagePartToPictureData方法)

具体加入的方法convertPackagePartToPictureData

/*** 将PackagePart转换为PictureData* @param packagePart* @param workbook* @return*/public static PictureData convertPackagePartToPictureData(PackagePart packagePart, XSSFWorkbook workbook) {if (packagePart == null) {throw new IllegalArgumentException("PackagePart cannot be null");}if (workbook == null) {throw new IllegalArgumentException("Workbook cannot be null");}try (InputStream inputStream = packagePart.getInputStream()) {// 从PackagePart读取数据byte[] data = IOUtils.toByteArray(inputStream);// 确定内容,创建PictureTypeString contentType = packagePart.getContentType();// 默认PNGint pictureType = XSSFWorkbook.PICTURE_TYPE_PNG;if (contentType.equals("image/jpeg")) {pictureType = XSSFWorkbook.PICTURE_TYPE_JPEG;} else if (contentType.equals("image/png")) {pictureType = XSSFWorkbook.PICTURE_TYPE_PNG;}// 将图片数据添加到工作簿int pictureIndex = workbook.addPicture(data, pictureType);return workbook.getAllPictures().get(pictureIndex);} catch (IOException e) {e.printStackTrace();return null;}}

四、总结

具体使用的文件为下面四个
在这里插入图片描述

1、ExcelImportServer代码

/*** Copyright 2013-2015 JEECG (jeecgos@163.com)* <p>* Licensed under the Apache License, Version 2.0 (the "License");* you may not use this file except in compliance with the License.* You may obtain a copy of the License at* <p>* http://www.apache.org/licenses/LICENSE-2.0* <p>* Unless required by applicable law or agreed to in writing, software* distributed under the License is distributed on an "AS IS" BASIS,* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.* See the License for the specific language governing permissions and* limitations under the License.*/
package org.jeecgframework.poi.excel.imports;import org.apache.commons.lang3.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ooxml.util.PackageHelper;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.ss.formula.functions.T;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.jeecgframework.core.util.ApplicationContextUtil;
import org.jeecgframework.poi.excel.annotation.ExcelTarget;
import org.jeecgframework.poi.excel.entity.ImportParams;
import org.jeecgframework.poi.excel.entity.params.ExcelCollectionParams;
import org.jeecgframework.poi.excel.entity.params.ExcelImportEntity;
import org.jeecgframework.poi.excel.entity.result.ExcelImportResult;
import org.jeecgframework.poi.excel.entity.result.ExcelVerifyHanlderResult;
import org.jeecgframework.poi.excel.imports.base.ImportBaseService;
import org.jeecgframework.poi.excel.imports.base.ImportFileServiceI;
import org.jeecgframework.poi.excel.imports.verifys.VerifyHandlerServer;
import org.jeecgframework.poi.exception.excel.ExcelImportException;
import org.jeecgframework.poi.exception.excel.enums.ExcelImportEnum;
import org.jeecgframework.poi.util.ExcelUtil;
import org.jeecgframework.poi.util.PoiPublicUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;import java.io.*;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.*;/*** Excel 导入服务** @author JEECG* @date 2014年6月26日 下午9:20:51*/
@SuppressWarnings({"rawtypes", "unchecked", "hiding"})
public class ExcelImportServer extends ImportBaseService {private final static Logger LOGGER = LoggerFactory.getLogger(ExcelImportServer.class);private CellValueServer cellValueServer;private VerifyHandlerServer verifyHandlerServer;private boolean verfiyFail = false;/*** 异常数据styler*/private CellStyle errorCellStyle;public ExcelImportServer() {this.cellValueServer = new CellValueServer();this.verifyHandlerServer = new VerifyHandlerServer();}/**** 向List里面继续添加元素** @param object* @param param* @param row* @param titlemap* @param targetId* @param pictures* @param params*/private void addListContinue(Object object, ExcelCollectionParams param, Row row, Map<Integer, String> titlemap, String targetId, Map<String, PictureData> pictures, ImportParams params) throws Exception {Collection collection = (Collection) PoiPublicUtil.getMethod(param.getName(), object.getClass()).invoke(object, new Object[]{});Object entity = PoiPublicUtil.createObject(param.getType(), targetId);String picId;boolean isUsed = false;// 是否需要加上这个对象for (int i = row.getFirstCellNum(); i < row.getLastCellNum(); i++) {Cell cell = row.getCell(i);String titleString = (String) titlemap.get(i);if (param.getExcelParams().containsKey(titleString)) {if (param.getExcelParams().get(titleString).getType() == 2) {picId = row.getRowNum() + "_" + i;saveImage(object, picId, param.getExcelParams(), titleString, pictures, params);} else {saveFieldValue(params, entity, cell, param.getExcelParams(), titleString, row);}isUsed = true;}}if (isUsed) {collection.add(entity);}}/*** 获取key的值,针对不同类型获取不同的值** @Author JEECG* @date 2013-11-21* @param cell* @return*/private String getKeyValue(Cell cell) {if (cell == null) {return null;}Object obj = null;switch (cell.getCellTypeEnum()) {case STRING:obj = cell.getStringCellValue();break;case BOOLEAN:obj = cell.getBooleanCellValue();break;case NUMERIC:obj = cell.getNumericCellValue();break;case FORMULA:obj = cell.getCellFormula();break;}return obj == null ? null : obj.toString().trim();}/*** 获取保存的真实路径** @param excelImportEntity* @param object* @return* @throws Exception*/private String getSaveUrl(ExcelImportEntity excelImportEntity, Object object) throws Exception {String url = "";if (excelImportEntity.getSaveUrl().equals("upload")) {if (excelImportEntity.getMethods() != null && excelImportEntity.getMethods().size() > 0) {object = getFieldBySomeMethod(excelImportEntity.getMethods(), object);}url = object.getClass().getName().split("\\.")[object.getClass().getName().split("\\.").length - 1];return excelImportEntity.getSaveUrl() + "/" + url.substring(0, url.lastIndexOf("Entity"));}return excelImportEntity.getSaveUrl();}//update-begin--Author:xuelin  Date:20171205 for:TASK #2098 【excel问题】 Online 一对多导入失败--------------------private <T> List<T> importExcel(Collection<T> result, Sheet sheet, Class<?> pojoClass, ImportParams params, Map<String, PictureData> pictures) throws Exception {List collection = new ArrayList();Map<String, ExcelImportEntity> excelParams = new HashMap<String, ExcelImportEntity>();List<ExcelCollectionParams> excelCollection = new ArrayList<ExcelCollectionParams>();String targetId = null;if (!Map.class.equals(pojoClass)) {Field fileds[] = PoiPublicUtil.getClassFields(pojoClass);ExcelTarget etarget = pojoClass.getAnnotation(ExcelTarget.class);if (etarget != null) {targetId = etarget.value();}getAllExcelField(targetId, fileds, excelParams, excelCollection, pojoClass, null);}ignoreHeaderHandler(excelParams, params);Iterator<Row> rows = sheet.rowIterator();Map<Integer, String> titlemap = getTitleMap(sheet, rows, params, excelCollection);//update-begin-author:liusq date:20220310 for:[issues/I4PU45]@excel里面新增属性fixedIndexSet<String> keys = excelParams.keySet();for (String key : keys) {if (key.startsWith("FIXED_")) {String[] arr = key.split("_");titlemap.put(Integer.parseInt(arr[1]), key);}}//update-end-author:liusq date:20220310 for:[issues/I4PU45]@excel里面新增属性fixedIndexSet<Integer> columnIndexSet = titlemap.keySet();Integer maxColumnIndex = Collections.max(columnIndexSet);Integer minColumnIndex = Collections.min(columnIndexSet);Row row = null;//跳过表头和标题行for (int j = 0; j < params.getTitleRows() + params.getHeadRows(); j++) {row = rows.next();}Object object = null;String picId;while (rows.hasNext() && (row == null || sheet.getLastRowNum() - row.getRowNum() > params.getLastOfInvalidRow())) {row = rows.next();//update-begin--Author:xuelin  Date:20171017 for:TASK #2373 【bug】表改造问题,导致 3.7.1批量导入用户bug-导入不成功--------------------// 判断是集合元素还是不是集合元素,如果是就继续加入这个集合,不是就创建新的对象//update-begin--Author:xuelin  Date:20171206 for:TASK #2451 【excel导出bug】online 一对多导入成功, 但是现在代码生成后的一对多online导入有问题了Cell keyIndexCell = row.getCell(params.getKeyIndex());if (excelCollection.size() > 0 && StringUtils.isEmpty(getKeyValue(keyIndexCell)) && object != null && !Map.class.equals(pojoClass)) {//update-end--Author:xuelin  Date:20171206 for:TASK #2451 【excel导出bug】online 一对多导入成功, 但是现在代码生成后的一对多online导入有问题了for (ExcelCollectionParams param : excelCollection) {addListContinue(object, param, row, titlemap, targetId, pictures, params);}} else {object = PoiPublicUtil.createObject(pojoClass, targetId);try {//update-begin-author:taoyan date:20200303 for:导入图片int firstCellNum = row.getFirstCellNum();if (firstCellNum > minColumnIndex) {firstCellNum = minColumnIndex;}int lastCellNum = row.getLastCellNum();if (lastCellNum < maxColumnIndex + 1) {lastCellNum = maxColumnIndex + 1;}for (int i = firstCellNum, le = lastCellNum; i < le; i++) {Cell cell = row.getCell(i);String titleString = (String) titlemap.get(i);if (excelParams.containsKey(titleString) || Map.class.equals(pojoClass)) {if (excelParams.get(titleString) != null && excelParams.get(titleString).getType() == 2) {picId = row.getRowNum() + "_" + i;saveImage(object, picId, excelParams, titleString, pictures, params);} else {if (params.getImageList() != null && params.getImageList().contains(titleString)) {if (pictures != null) {picId = row.getRowNum() + "_" + i;PictureData image = pictures.get(picId);if (image != null) {byte[] data = image.getData();params.getDataHanlder().setMapValue((Map) object, titleString, data);}}} else {saveFieldValue(params, object, cell, excelParams, titleString, row);}//update-end-author:taoyan date:20200303 for:导入图片}}}for (ExcelCollectionParams param : excelCollection) {addListContinue(object, param, row, titlemap, targetId, pictures, params);}//update-begin-author:taoyan date:20210526 for:autopoi导入excel 如果单元格被设置边框,即使没有内容也会被当做是一条数据导入 #2484if (isNotNullObject(pojoClass, object)) {collection.add(object);}//update-end-author:taoyan date:20210526 for:autopoi导入excel 如果单元格被设置边框,即使没有内容也会被当做是一条数据导入 #2484} catch (ExcelImportException e) {if (!e.getType().equals(ExcelImportEnum.VERIFY_ERROR)) {throw new ExcelImportException(e.getType(), e);}}}//update-end--Author:xuelin  Date:20171017 for:TASK #2373 【bug】表改造问题,导致 3.7.1批量导入用户bug-导入不成功--------------------}return collection;}/*** 判断当前对象不是空* @param pojoClass* @param object* @return*/private boolean isNotNullObject(Class pojoClass, Object object) {try {Method method = pojoClass.getMethod("isNullObject");if (method != null) {Object flag = method.invoke(object);if (flag != null && true == Boolean.parseBoolean(flag.toString())) {return false;}}} catch (NoSuchMethodException e) {LOGGER.debug("未定义方法 isNullObject");} catch (IllegalAccessException e) {LOGGER.warn("没有权限访问该方法 isNullObject");} catch (InvocationTargetException e) {LOGGER.warn("方法调用失败 isNullObject");}return true;}/*** 获取忽略的表头信息* @param excelParams* @param params*/private void ignoreHeaderHandler(Map<String, ExcelImportEntity> excelParams, ImportParams params) {List<String> ignoreList = new ArrayList<>();for (String key : excelParams.keySet()) {String temp = excelParams.get(key).getGroupName();if (temp != null && temp.length() > 0) {ignoreList.add(temp);}}params.setIgnoreHeaderList(ignoreList);}/*** 获取表格字段列名对应信息** @param rows* @param params* @param excelCollection* @return*/private Map<Integer, String> getTitleMap(Sheet sheet, Iterator<Row> rows, ImportParams params, List<ExcelCollectionParams> excelCollection) throws Exception {Map<Integer, String> titlemap = new HashMap<Integer, String>();Iterator<Cell> cellTitle = null;String collectionName = null;ExcelCollectionParams collectionParams = null;Row headRow = null;int headBegin = params.getTitleRows();//update_begin-author:taoyan date:2020622 for:当文件行数小于代码里设置的TitleRows时headRow一直为空就会出现死循环int allRowNum = sheet.getPhysicalNumberOfRows();//找到首行表头,每个sheet都必须至少有一行表头while (headRow == null && headBegin < allRowNum) {headRow = sheet.getRow(headBegin++);}if (headRow == null) {throw new Exception("不识别该文件");}//update-end-author:taoyan date:2020622 for:当文件行数小于代码里设置的TitleRows时headRow一直为空就会出现死循环//设置表头行数if (ExcelUtil.isMergedRegion(sheet, headRow.getRowNum(), 0)) {params.setHeadRows(2);} else {params.setHeadRows(1);}cellTitle = headRow.cellIterator();while (cellTitle.hasNext()) {Cell cell = cellTitle.next();String value = getKeyValue(cell);if (StringUtils.isNotEmpty(value)) {titlemap.put(cell.getColumnIndex(), value);//加入表头列表}}//多行表头for (int j = headBegin; j < headBegin + params.getHeadRows() - 1; j++) {headRow = sheet.getRow(j);cellTitle = headRow.cellIterator();while (cellTitle.hasNext()) {Cell cell = cellTitle.next();String value = getKeyValue(cell);if (StringUtils.isNotEmpty(value)) {int columnIndex = cell.getColumnIndex();//当前cell的上一行是否为合并单元格if (ExcelUtil.isMergedRegion(sheet, cell.getRowIndex() - 1, columnIndex)) {collectionName = ExcelUtil.getMergedRegionValue(sheet, cell.getRowIndex() - 1, columnIndex);if (params.isIgnoreHeader(collectionName)) {titlemap.put(cell.getColumnIndex(), value);} else {titlemap.put(cell.getColumnIndex(), collectionName + "_" + value);}} else {//update-begin-author:taoyan date:20220112 for: JT640 【online】导入 无论一对一还是一对多 如果子表只有一个字段 则子表无数据// 上一行不是合并的情况下另有一种特殊的场景: 如果当前单元格和上面的单元格同一列 即子表字段只有一个 所以标题没有出现跨列String prefixTitle = titlemap.get(cell.getColumnIndex());if (prefixTitle != null && !"".equals(prefixTitle)) {titlemap.put(cell.getColumnIndex(), prefixTitle + "_" + value);} else {titlemap.put(cell.getColumnIndex(), value);}//update-end-author:taoyan date:20220112 for: JT640 【online】导入 无论一对一还是一对多 如果子表只有一个字段 则子表无数据}/*int i = cell.getColumnIndex();// 用以支持重名导入if (titlemap.containsKey(i)) {collectionName = titlemap.get(i);collectionParams = getCollectionParams(excelCollection, collectionName);titlemap.put(i, collectionName + "_" + value);} else if (StringUtils.isNotEmpty(collectionName) && collectionParams.getExcelParams().containsKey(collectionName + "_" + value)) {titlemap.put(i, collectionName + "_" + value);} else {collectionName = null;collectionParams = null;}if (StringUtils.isEmpty(collectionName)) {titlemap.put(i, value);}*/}}}return titlemap;}//update-end--Author:xuelin  Date:20171205 for:TASK #2098 【excel问题】 Online 一对多导入失败--------------------/*** 获取这个名称对应的集合信息** @param excelCollection* @param collectionName* @return*/private ExcelCollectionParams getCollectionParams(List<ExcelCollectionParams> excelCollection, String collectionName) {for (ExcelCollectionParams excelCollectionParams : excelCollection) {if (collectionName.equals(excelCollectionParams.getExcelName())) {return excelCollectionParams;}}return null;}/*** Excel 导入 field 字段类型 Integer,Long,Double,Date,String,Boolean** @param inputstream* @param pojoClass* @param params* @return* @throws Exception*/public ExcelImportResult importExcelByIs(InputStream inputstream, Class<?> pojoClass, ImportParams params) throws Exception {if (LOGGER.isDebugEnabled()) {LOGGER.debug("Excel import start ,class is {}", pojoClass);}List<T> result = new ArrayList<T>();Workbook book = null;OPCPackage opc = null;boolean isXSSFWorkbook = false;if (!(inputstream.markSupported())) {inputstream = new PushbackInputStream(inputstream, 8);}//begin-------author:liusq------date:20210129-----for:-------poi3升级到4兼容改造工作【重要敏感修改点】--------//------poi4.x begin----
//		FileMagic fm = FileMagic.valueOf(FileMagic.prepareToCheckMagic(inputstream));
//		if(FileMagic.OLE2 == fm){
//			isXSSFWorkbook=false;
//		}// 将输入流内容复制到字节数组ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();byte[] buffer = new byte[1024];int bytesRead;while ((bytesRead = inputstream.read(buffer)) != -1) {byteArrayOutputStream.write(buffer, 0, bytesRead);}byte[] workbookData = byteArrayOutputStream.toByteArray();try (ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(workbookData)) {// 创建Workbook,不会直接关闭原始输入流book = WorkbookFactory.create(byteArrayInputStream);if (book instanceof XSSFWorkbook) {isXSSFWorkbook = true;opc = PackageHelper.open(new ByteArrayInputStream(workbookData));}} finally {try {//之前操作自动关闭了输入流,由于输入流内容复制到字节数组没有进行关闭,所以这里进行关闭inputstream.close();} catch (IOException e) {LOGGER.info("Error closing input stream: " + e.getMessage());}}
//        book = WorkbookFactory.create(nonClosingInputStream);
//        if (book instanceof XSSFWorkbook) {
//            isXSSFWorkbook = true;
//            opc = PackageHelper.open(inputstream);
//        }LOGGER.info("  >>>  poi3升级到4.0兼容改造工作, isXSSFWorkbook = " + isXSSFWorkbook);//end-------author:liusq------date:20210129-----for:-------poi3升级到4兼容改造工作【重要敏感修改点】--------//begin-------author:liusq------date:20210313-----for:-------多sheet导入改造点--------//获取导入文本的sheet数//update-begin-author:taoyan date:20211210 for:https://gitee.com/jeecg/jeecg-boot/issues/I45C32 导入空白sheet报错if (params.getSheetNum() == 0) {int sheetNum = book.getNumberOfSheets();if (sheetNum > 0) {params.setSheetNum(sheetNum);}}//update-end-author:taoyan date:20211210 for:https://gitee.com/jeecg/jeecg-boot/issues/I45C32 导入空白sheet报错//end-------author:liusq------date:20210313-----for:-------多sheet导入改造点--------createErrorCellStyle(book);Map<String, PictureData> pictures;//update-begin-author:liusq date:20220609 for:issues/I57UPC excel导入 ImportParams 中没有startSheetIndex参数for (int i = params.getStartSheetIndex(); i < params.getStartSheetIndex()+ params.getSheetNum(); i++) {//update-end-author:liusq date:20220609 for:issues/I57UPC excel导入 ImportParams 中没有startSheetIndex参数if (LOGGER.isDebugEnabled()) {LOGGER.debug(" start to read excel by is ,startTime is {}", System.currentTimeMillis());}//03版xls因为文件限制暂时无法识别内嵌图片//07版xlsx 此处以进行适配内嵌图片,内嵌和浮动自动识别返回if (isXSSFWorkbook) {pictures = PoiPublicUtil.getAllPictures(opc,(XSSFSheet) book.getSheetAt(i), (XSSFWorkbook) book);
//                pictures = PoiPublicUtil.getSheetPictrues07((XSSFSheet) book.getSheetAt(i), (XSSFWorkbook) book);} else {pictures = PoiPublicUtil.getSheetPictrues03((HSSFSheet) book.getSheetAt(i), (HSSFWorkbook) book);}if (LOGGER.isDebugEnabled()) {LOGGER.debug(" end to read excel by is ,endTime is {}", new Date().getTime());}result.addAll(importExcel(result, book.getSheetAt(i), pojoClass, params, pictures));if (LOGGER.isDebugEnabled()) {LOGGER.debug(" end to read excel list by pos ,endTime is {}", new Date().getTime());}}if (params.isNeedSave()) {saveThisExcel(params, pojoClass, isXSSFWorkbook, book);}return new ExcelImportResult(result, verfiyFail, book);}/**** @param is* @return* @throws IOException*/public static byte[] getBytes(InputStream is) throws IOException {ByteArrayOutputStream buffer = new ByteArrayOutputStream();int len;byte[] data = new byte[100000];while ((len = is.read(data, 0, data.length)) != -1) {buffer.write(data, 0, len);}buffer.flush();return buffer.toByteArray();}/*** 保存字段值(获取值,校验值,追加错误信息)** @param params* @param object* @param cell* @param excelParams* @param titleString* @param row* @throws Exception*/private void saveFieldValue(ImportParams params, Object object, Cell cell, Map<String, ExcelImportEntity> excelParams, String titleString, Row row) throws Exception {Object value = cellValueServer.getValue(params.getDataHanlder(), object, cell, excelParams, titleString);if (object instanceof Map) {if (params.getDataHanlder() != null) {params.getDataHanlder().setMapValue((Map) object, titleString, value);} else {((Map) object).put(titleString, value);}} else {ExcelVerifyHanlderResult verifyResult = verifyHandlerServer.verifyData(object, value, titleString, excelParams.get(titleString).getVerify(), params.getVerifyHanlder());if (verifyResult.isSuccess()) {setValues(excelParams.get(titleString), object, value);} else {Cell errorCell = row.createCell(row.getLastCellNum());errorCell.setCellValue(verifyResult.getMsg());errorCell.setCellStyle(errorCellStyle);verfiyFail = true;throw new ExcelImportException(ExcelImportEnum.VERIFY_ERROR);}}}/**** @param object* @param picId* @param excelParams* @param titleString* @param pictures* @param params* @throws Exception*/private void saveImage(Object object, String picId, Map<String, ExcelImportEntity> excelParams, String titleString, Map<String, PictureData> pictures, ImportParams params) throws Exception {if (pictures == null || pictures.get(picId) == null) {return;}PictureData image = pictures.get(picId);byte[] data = image.getData();String fileName = "pic" + Math.round(Math.random() * 100000000000L);fileName += "." + PoiPublicUtil.getFileExtendName(data);//update-beign-author:taoyan date:20200302 for:【多任务】online 专项集中问题 LOWCOD-159int saveType = excelParams.get(titleString).getSaveType();if (saveType == 1) {String path = PoiPublicUtil.getWebRootPath(getSaveUrl(excelParams.get(titleString), object));File savefile = new File(path);if (!savefile.exists()) {savefile.mkdirs();}savefile = new File(path + "/" + fileName);FileOutputStream fos = new FileOutputStream(savefile);fos.write(data);fos.close();setValues(excelParams.get(titleString), object, getSaveUrl(excelParams.get(titleString), object) + "/" + fileName);} else if (saveType == 2) {setValues(excelParams.get(titleString), object, data);} else {ImportFileServiceI importFileService = null;try {importFileService = ApplicationContextUtil.getContext().getBean(ImportFileServiceI.class);} catch (Exception e) {System.err.println(e.getMessage());}if (importFileService != null) {String dbPath = importFileService.doUpload(data);setValues(excelParams.get(titleString), object, dbPath);}}//update-end-author:taoyan date:20200302 for:【多任务】online 专项集中问题 LOWCOD-159}private void createErrorCellStyle(Workbook workbook) {errorCellStyle = workbook.createCellStyle();Font font = workbook.createFont();font.setColor(Font.COLOR_RED);errorCellStyle.setFont(font);}}

2、PoiPublicUtil代码

/*** Copyright 2013-2015 JEECG (jeecgos@163.com)**  Licensed under the Apache License, Version 2.0 (the "License");*  you may not use this file except in compliance with the License.*  You may obtain a copy of the License at**     http://www.apache.org/licenses/LICENSE-2.0**  Unless required by applicable law or agreed to in writing, software* distributed under the License is distributed on an "AS IS" BASIS,* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.* See the License for the specific language governing permissions and* limitations under the License.*/
package org.jeecgframework.poi.util;import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.net.URISyntaxException;
import java.util.*;import javax.imageio.ImageIO;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;import org.apache.commons.lang3.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFClientAnchor;
import org.apache.poi.hssf.usermodel.HSSFPicture;
import org.apache.poi.hssf.usermodel.HSSFPictureData;
import org.apache.poi.hssf.usermodel.HSSFShape;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ooxml.POIXMLDocumentPart;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.openxml4j.opc.PackagePart;
import org.apache.poi.openxml4j.opc.PackagePartName;
import org.apache.poi.ss.usermodel.PictureData;
import org.apache.poi.util.IOUtils;
import org.apache.poi.xssf.usermodel.XSSFClientAnchor;
import org.apache.poi.xssf.usermodel.XSSFDrawing;
import org.apache.poi.xssf.usermodel.XSSFPicture;
import org.apache.poi.xssf.usermodel.XSSFShape;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.jdom2.Attribute;
import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.JDOMException;
import org.jdom2.input.SAXBuilder;
import org.jeecgframework.poi.excel.annotation.Excel;
import org.jeecgframework.poi.excel.annotation.ExcelCollection;
import org.jeecgframework.poi.excel.annotation.ExcelEntity;
import org.jeecgframework.poi.excel.annotation.ExcelIgnore;
import org.jeecgframework.poi.excel.entity.vo.PoiBaseConstants;
import org.jeecgframework.poi.word.entity.WordImageEntity;
import org.jeecgframework.poi.word.entity.params.ExcelListEntity;
import org.jeecgframework.poi.xml.SAXParserHandler;
import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.CTMarker;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.ClassUtils;
import org.xml.sax.SAXException;/*** AutoPoi 的公共基础类** @author JEECG* @date 2015年4月5日 上午12:59:22*/
public final class PoiPublicUtil {private static final Logger LOGGER = LoggerFactory.getLogger(PoiPublicUtil.class);private PoiPublicUtil() {}@SuppressWarnings({ "unchecked" })public static <K, V> Map<K, V> mapFor(Object... mapping) {Map<K, V> map = new HashMap<K, V>();for (int i = 0; i < mapping.length; i += 2) {map.put((K) mapping[i], (V) mapping[i + 1]);}return map;}/*** 彻底创建一个对象** @param clazz* @return*/public static Object createObject(Class<?> clazz, String targetId) {Object obj = null;Method setMethod;try {if (clazz.equals(Map.class)) {return new HashMap<String, Object>();}obj = clazz.newInstance();Field[] fields = getClassFields(clazz);for (Field field : fields) {if (isNotUserExcelUserThis(null, field, targetId)) {continue;}if (isCollection(field.getType())) {ExcelCollection collection = field.getAnnotation(ExcelCollection.class);setMethod = getMethod(field.getName(), clazz, field.getType());setMethod.invoke(obj, collection.type().newInstance());} else if (!isJavaClass(field)) {setMethod = getMethod(field.getName(), clazz, field.getType());setMethod.invoke(obj, createObject(field.getType(), targetId));}}} catch (Exception e) {LOGGER.error(e.getMessage(), e);throw new RuntimeException("创建对象异常");}return obj;}/*** 获取class的 包括父类的** @param clazz* @return*/public static Field[] getClassFields(Class<?> clazz) {List<Field> list = new ArrayList<Field>();Field[] fields;do {fields = clazz.getDeclaredFields();for (int i = 0; i < fields.length; i++) {list.add(fields[i]);}clazz = clazz.getSuperclass();} while (clazz != Object.class && clazz != null);return list.toArray(fields);}/*** @param photoByte* @return*/public static String getFileExtendName(byte[] photoByte) {String strFileExtendName = "JPG";if ((photoByte[0] == 71) && (photoByte[1] == 73) && (photoByte[2] == 70) && (photoByte[3] == 56) && ((photoByte[4] == 55) || (photoByte[4] == 57)) && (photoByte[5] == 97)) {strFileExtendName = "GIF";} else if ((photoByte[6] == 74) && (photoByte[7] == 70) && (photoByte[8] == 73) && (photoByte[9] == 70)) {strFileExtendName = "JPG";} else if ((photoByte[0] == 66) && (photoByte[1] == 77)) {strFileExtendName = "BMP";} else if ((photoByte[1] == 80) && (photoByte[2] == 78) && (photoByte[3] == 71)) {strFileExtendName = "PNG";}return strFileExtendName;}/*** 获取GET方法** @param name* @param pojoClass* @return* @throws Exception*/public static Method getMethod(String name, Class<?> pojoClass) throws Exception {StringBuffer getMethodName = new StringBuffer(PoiBaseConstants.GET);getMethodName.append(name.substring(0, 1).toUpperCase());getMethodName.append(name.substring(1));Method method = null;try {method = pojoClass.getMethod(getMethodName.toString(), new Class[] {});} catch (Exception e) {method = pojoClass.getMethod(getMethodName.toString().replace(PoiBaseConstants.GET, PoiBaseConstants.IS), new Class[] {});}return method;}/*** 获取SET方法** @param name* @param pojoClass* @param type* @return* @throws Exception*/public static Method getMethod(String name, Class<?> pojoClass, Class<?> type) throws Exception {StringBuffer getMethodName = new StringBuffer(PoiBaseConstants.SET);getMethodName.append(name.substring(0, 1).toUpperCase());getMethodName.append(name.substring(1));return pojoClass.getMethod(getMethodName.toString(), new Class[] { type });}//update-begin-author:taoyan date:20180615 for:TASK #2798 导入扩展方法,支持自定义导入字段转换规则/*** 获取get方法 通过EXCEL注解exportConvert判断是否支持值的转换* @param name* @param pojoClass* @param convert* @return* @throws Exception*/public static Method getMethod(String name, Class<?> pojoClass,boolean convert) throws Exception {StringBuffer getMethodName = new StringBuffer();if(convert){getMethodName.append(PoiBaseConstants.CONVERT);}getMethodName.append(PoiBaseConstants.GET);getMethodName.append(name.substring(0, 1).toUpperCase());getMethodName.append(name.substring(1));Method method = null;try {method = pojoClass.getMethod(getMethodName.toString(), new Class[] {});} catch (Exception e) {method = pojoClass.getMethod(getMethodName.toString().replace(PoiBaseConstants.GET, PoiBaseConstants.IS), new Class[] {});}return method;}/*** 获取set方法  通过EXCEL注解importConvert判断是否支持值的转换* @param name* @param pojoClass* @param type* @param convert* @return* @throws Exception*/public static Method getMethod(String name, Class<?> pojoClass, Class<?> type,boolean convert) throws Exception {StringBuffer setMethodName = new StringBuffer();if(convert){setMethodName.append(PoiBaseConstants.CONVERT);}setMethodName.append(PoiBaseConstants.SET);setMethodName.append(name.substring(0, 1).toUpperCase());setMethodName.append(name.substring(1));return pojoClass.getMethod(setMethodName.toString(), new Class[] { type });}//update-end-author:taoyan date:20180615 for:TASK #2798 导入扩展方法,支持自定义导入字段转换规则/*** 获取Excel2003图片** @param sheet*            当前sheet对象* @param workbook*            工作簿对象* @return Map key:图片单元格索引(1_1)String,value:图片流PictureData*/public static Map<String, PictureData> getSheetPictrues03(HSSFSheet sheet, HSSFWorkbook workbook) {Map<String, PictureData> sheetIndexPicMap = new HashMap<String, PictureData>();List<HSSFPictureData> pictures = workbook.getAllPictures();if (!pictures.isEmpty()) {for (HSSFShape shape : sheet.getDrawingPatriarch().getChildren()) {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());sheetIndexPicMap.put(picIndex, picData);}}return sheetIndexPicMap;} else {return null;}}/*** 获取Excel2007图片** @param sheet*            当前sheet对象* @param workbook*            工作簿对象* @return Map key:图片单元格索引(1_1)String,value:图片流PictureData*/public static Map<String, PictureData> getSheetPictrues07(XSSFSheet sheet, XSSFWorkbook workbook) {Map<String, PictureData> sheetIndexPicMap = new HashMap<String, PictureData>();for (POIXMLDocumentPart dr : sheet.getRelations()) {if (dr instanceof XSSFDrawing) {XSSFDrawing drawing = (XSSFDrawing) dr;List<XSSFShape> shapes = drawing.getShapes();for (XSSFShape shape : shapes) {XSSFPicture pic = (XSSFPicture) shape;XSSFClientAnchor anchor = pic.getPreferredSize();CTMarker ctMarker = anchor.getFrom();String picIndex = ctMarker.getRow() + "_" + ctMarker.getCol();sheetIndexPicMap.put(picIndex, pic.getPictureData());}}}return sheetIndexPicMap;}public static Map<String, PictureData> getAllPictures(OPCPackage opc, XSSFSheet sheet, XSSFWorkbook workbook) throws Exception {Map<String, PictureData> sheetIndexPicMap = new HashMap<>();// 处理嵌入式图片List<PackagePart> parts = opc.getParts();sheetIndexPicMap.putAll(getEmbedPictures(parts));// 处理浮动式图片sheetIndexPicMap.putAll(getSheetPictrues07(sheet, workbook));return sheetIndexPicMap;}public static String getWebRootPath(String filePath) {try {String path = null;try {path = PoiPublicUtil.class.getClassLoader().getResource("").toURI().getPath();} catch (URISyntaxException e) {//e.printStackTrace();//update-begin-author:taoyan date:20211116 for: JAR包分离 发布出空指针 https://gitee.com/jeecg/jeecg-boot/issues/I4CMHK}catch (NullPointerException e) {path =  PoiPublicUtil.class.getProtectionDomain().getCodeSource().getLocation().getPath();}//update-end-author:taoyan date:20211116 for: JAR包分离 发布出空指针 https://gitee.com/jeecg/jeecg-boot/issues/I4CMHK//update-begin--Author:zhangdaihao  Date:20190424 for:解决springboot 启动模式,上传路径获取为空问题---------------------if (path == null || path == "") {//解决springboot 启动模式,上传路径获取为空问题path = ClassUtils.getDefaultClassLoader().getResource("").getPath();}//update-end--Author:zhangdaihao  Date:20190424 for:解决springboot 启动模式,上传路径获取为空问题----------------------LOGGER.debug("--- getWebRootPath ----filePath--- " + path);path = path.replace("WEB-INF/classes/", "");path = path.replace("file:/", "");LOGGER.debug("--- path---  " + path);LOGGER.debug("--- filePath---  " + filePath);return path + filePath;} catch (Exception e) {throw new RuntimeException(e);}}/*** 判断是不是集合的实现类** @param clazz* @return*/public static boolean isCollection(Class<?> clazz) {return Collection.class.isAssignableFrom(clazz);}/*** 是不是java基础类** @param field* @return*/public static boolean isJavaClass(Field field) {Class<?> fieldType = field.getType();boolean isBaseClass = false;if (fieldType.isArray()) {isBaseClass = false;} else if (fieldType.isPrimitive() || fieldType.getPackage() == null || fieldType.getPackage().getName().equals("java.lang") || fieldType.getPackage().getName().equals("java.math") || fieldType.getPackage().getName().equals("java.sql") || fieldType.getPackage().getName().equals("java.util")) {isBaseClass = true;}return isBaseClass;}/*** 判断是否不要在这个excel操作中** @param* @param field* @param targetId* @return*/public static boolean isNotUserExcelUserThis(List<String> exclusionsList, Field field, String targetId) {boolean boo = true;if (field.getAnnotation(ExcelIgnore.class) != null) {boo = true;} else if (boo && field.getAnnotation(ExcelCollection.class) != null && isUseInThis(field.getAnnotation(ExcelCollection.class).name(), targetId) && (exclusionsList == null || !exclusionsList.contains(field.getAnnotation(ExcelCollection.class).name()))) {boo = false;} else if (boo && field.getAnnotation(Excel.class) != null && isUseInThis(field.getAnnotation(Excel.class).name(), targetId) && (exclusionsList == null || !exclusionsList.contains(field.getAnnotation(Excel.class).name()))) {boo = false;} else if (boo && field.getAnnotation(ExcelEntity.class) != null && isUseInThis(field.getAnnotation(ExcelEntity.class).name(), targetId) && (exclusionsList == null || !exclusionsList.contains(field.getAnnotation(ExcelEntity.class).name()))) {boo = false;}return boo;}/*** 判断是不是使用** @param exportName* @param targetId* @return*/private static boolean isUseInThis(String exportName, String targetId) {return targetId == null || exportName.equals("") || exportName.indexOf("_") < 0 || exportName.indexOf(targetId) != -1;}private static Integer getImageType(String type) {if (type.equalsIgnoreCase("JPG") || type.equalsIgnoreCase("JPEG")) {return XWPFDocument.PICTURE_TYPE_JPEG;}if (type.equalsIgnoreCase("GIF")) {return XWPFDocument.PICTURE_TYPE_GIF;}if (type.equalsIgnoreCase("BMP")) {return XWPFDocument.PICTURE_TYPE_GIF;}if (type.equalsIgnoreCase("PNG")) {return XWPFDocument.PICTURE_TYPE_PNG;}return XWPFDocument.PICTURE_TYPE_JPEG;}/*** 返回流和图片类型** @Author JEECG* @date 2013-11-20* @param entity* @return (byte[]) isAndType[0],(Integer)isAndType[1]* @throws Exception*/public static Object[] getIsAndType(WordImageEntity entity) throws Exception {Object[] result = new Object[2];String type;if (entity.getType().equals(WordImageEntity.URL)) {ByteArrayOutputStream byteArrayOut = new ByteArrayOutputStream();BufferedImage bufferImg;String path = Thread.currentThread().getContextClassLoader().getResource("").toURI().getPath() + entity.getUrl();path = path.replace("WEB-INF/classes/", "");path = path.replace("file:/", "");bufferImg = ImageIO.read(new File(path));//update-begin-author:taoYan date:20211203 for: Excel 导出图片的文件带小数点符号 导出报错 https://gitee.com/jeecg/jeecg-boot/issues/I4JNHRImageIO.write(bufferImg, entity.getUrl().substring(entity.getUrl().lastIndexOf(".") + 1, entity.getUrl().length()), byteArrayOut);//update-end-author:taoYan date:20211203 for: Excel 导出图片的文件带小数点符号 导出报错 https://gitee.com/jeecg/jeecg-boot/issues/I4JNHRresult[0] = byteArrayOut.toByteArray();type = entity.getUrl().split("/.")[entity.getUrl().split("/.").length - 1];} else {result[0] = entity.getData();type = PoiPublicUtil.getFileExtendName(entity.getData());}result[1] = getImageType(type);return result;}/*** 获取参数值** @param params* @param map* @return*/@SuppressWarnings("rawtypes")public static Object getParamsValue(String params, Object object) throws Exception {if (params.indexOf(".") != -1) {String[] paramsArr = params.split("\\.");return getValueDoWhile(object, paramsArr, 0);}if (object instanceof Map) {return ((Map) object).get(params);}return getMethod(params, object.getClass()).invoke(object, new Object[] {});}/*** 解析数据** @Author JEECG* @date 2013-11-16* @return*/public static Object getRealValue(String currentText, Map<String, Object> map) throws Exception {String params = "";while (currentText.indexOf("{{") != -1) {params = currentText.substring(currentText.indexOf("{{") + 2, currentText.indexOf("}}"));Object obj = getParamsValue(params.trim(), map);// 判断图片或者是集合// update-begin-author:taoyan date:20210914 for:autopoi模板导出,赋值的方法建议增加空判断或抛出异常说明。 /issues/3005if(obj==null){obj = "";}// update-end-author:taoyan date:20210914 for:autopoi模板导出,赋值的方法建议增加空判断或抛出异常说明。/issues/3005if (obj instanceof WordImageEntity || obj instanceof List || obj instanceof ExcelListEntity) {return obj;} else {currentText = currentText.replace("{{" + params + "}}", obj.toString());}}return currentText;}/*** 通过遍历过去对象值** @param object* @param paramsArr* @param index* @return* @throws Exception*/@SuppressWarnings("rawtypes")public static Object getValueDoWhile(Object object, String[] paramsArr, int index) throws Exception {if (object == null) {return "";}if (object instanceof WordImageEntity) {return object;}if (object instanceof Map) {object = ((Map) object).get(paramsArr[index]);} else {object = getMethod(paramsArr[index], object.getClass()).invoke(object, new Object[] {});}return (index == paramsArr.length - 1) ? (object == null ? "" : object) : getValueDoWhile(object, paramsArr, ++index);}/*** double to String 防止科学计数法** @param value* @return*/public static String doubleToString(Double value) {String temp = value.toString();if (temp.contains("E")) {BigDecimal bigDecimal = new BigDecimal(temp);temp = bigDecimal.toPlainString();}//---update-begin-----autor:scott------date:20191016-------for:excel导入数字类型,去掉后缀.0------return ExcelUtil.remove0Suffix(temp);//---update-end-----autor:scott------date:20191016-------for:excel导入数字类型,去掉后缀.0------}/*** 判断是否是数值类型* @param xclass* @return*/public static boolean isNumber(String xclass){if(xclass==null){return false;}String temp = xclass.toLowerCase();if(temp.indexOf("int")>=0 || temp.indexOf("double")>=0 || temp.indexOf("decimal")>=0){return true;}return false;}//update-begin---author:liusq  Date:20211217  for:[LOWCOD-2521]【autopoi】大数据导出方法【全局】----/*** 统一 key的获取规则* @param key* @param targetId* @date  2022年1月4号* @return*/public static String getValueByTargetId(String key, String targetId, String defalut) {if (StringUtils.isEmpty(targetId) || key.indexOf("_") < 0) {return key;}String[] arr = key.split(",");String[] tempArr;for (String str : arr) {tempArr = str.split("_");if (tempArr == null || tempArr.length < 2) {return defalut;}if (targetId.equals(tempArr[1])) {return tempArr[0];}}return defalut;}//update-end---author:liusq  Date:20211217  for:[LOWCOD-2521]【autopoi】大数据导出方法【全局】----/*** 将PackagePart转换为PictureData* @param packagePart* @param workbook* @return*/public static PictureData convertPackagePartToPictureData(PackagePart packagePart, XSSFWorkbook workbook) {if (packagePart == null) {throw new IllegalArgumentException("PackagePart cannot be null");}if (workbook == null) {throw new IllegalArgumentException("Workbook cannot be null");}try (InputStream inputStream = packagePart.getInputStream()) {// 从PackagePart读取数据byte[] data = IOUtils.toByteArray(inputStream);// 确定内容,创建PictureTypeString contentType = packagePart.getContentType();// 默认PNGint pictureType = XSSFWorkbook.PICTURE_TYPE_PNG;if (contentType.equals("image/jpeg")) {pictureType = XSSFWorkbook.PICTURE_TYPE_JPEG;} else if (contentType.equals("image/png")) {pictureType = XSSFWorkbook.PICTURE_TYPE_PNG;}// 将图片数据添加到工作簿int pictureIndex = workbook.addPicture(data, pictureType);return workbook.getAllPictures().get(pictureIndex);} catch (IOException e) {e.printStackTrace();return null;}}/*** 获取嵌入式图片* @param parts* @return* @throws JDOMException* @throws IOException* @throws ParserConfigurationException*/private static Map<String, PictureData> getEmbedPictures(List<PackagePart> parts) throws JDOMException, IOException, ParserConfigurationException, SAXException {Map<String, Set<String>> mapImg = new HashMap<>();Map<String, String> mapImgPath = new HashMap<>();Map<Integer, List<String>> dataMap = new HashMap<>();for (PackagePart part : parts) {
//            System.out.println(part.getPartName());PackagePartName partName = part.getPartName();String name = partName.getName();if ("/xl/cellimages.xml".equals(name)) {SAXBuilder builder = new SAXBuilder();// 获取文档Document doc = builder.build(part.getInputStream());// 获取根节点Element root = doc.getRootElement();List<Element> cellImageList = root.getChildren();for (Element imgEle : cellImageList) {Element xdrPic = imgEle.getChildren().get(0);Element xdrNvPicPr = xdrPic.getChildren().get(0);Element xdrBlipFill = xdrPic.getChildren().get(1);Element aBlip = xdrBlipFill.getChildren().get(0);Attribute attr = aBlip.getAttributes().get(0);String imgId = xdrNvPicPr.getChildren().get(0).getAttributeValue("name");String id = attr.getValue();if (mapImg.containsKey(id)) {mapImg.get(id).add(imgId);} else {Set<String> set = new HashSet<>();set.add(imgId);mapImg.put(id, set);}}}if ("/xl/_rels/cellimages.xml.rels".equals(name)) {SAXBuilder builder = new SAXBuilder();// 获取文档Document doc = builder.build(part.getInputStream());// 获取根节点Element root = doc.getRootElement();List<Element> relationshipList = root.getChildren();for (Element relationship : relationshipList) {String id = relationship.getAttributeValue("Id");String target = relationship.getAttributeValue("Target");mapImgPath.put(id, target);}}if (name.contains("/xl/worksheets/sheet")) {// 获取文档String sheetNoStr = name.replace("/xl/worksheets/sheet", "").replace(".xml", "");Integer sheetNo = Integer.valueOf(sheetNoStr) - 1;// 步骤1:创建SAXParserFactory实例SAXParserFactory factory = SAXParserFactory.newInstance();// 步骤2:创建SAXParser实例SAXParser saxParser = factory.newSAXParser();SAXParserHandler saxParserHandler = new SAXParserHandler();saxParser.parse(part.getInputStream(), saxParserHandler);List<String> rows = saxParserHandler.getRows();dataMap.put(sheetNo, rows);}}Map<String, String> imgMap = new HashMap<>();for (String id : mapImg.keySet()) {Set<String> imgIds = mapImg.get(id);String path = mapImgPath.get(id);for (String imgId : imgIds) {imgMap.put(imgId, path);}}for (Integer key : dataMap.keySet()) {List<String> rows = dataMap.get(key);for (int i = 0; i < rows.size(); i++) {String imgId = rows.get(i);String imgId_index = imgId.substring(0, imgId.indexOf(":"));String imgId_url = imgId.substring(imgId.indexOf(":")+1);if (imgMap.containsKey(imgId_url)) {rows.set(i, imgId_index+":"+imgMap.get(imgId_url));}}}Map<String, PictureData> map = new HashMap<>();for (Integer key : dataMap.keySet()) {List<String> pathList = dataMap.get(key);for (int i = 0; i < pathList.size(); i++) {String path = pathList.get(i);String path_index = path.substring(0, path.indexOf(":"));String path_url = path.substring(path.indexOf(":")+1);if (StringUtils.isNotEmpty(path_url)) {for (PackagePart part : parts) {PackagePartName partName = part.getPartName();String name = partName.getName();if (name.contains(path_url)) {//进行转换PictureData pictureData = convertPackagePartToPictureData(part,new XSSFWorkbook());map.put(path_index, pictureData);break;}}}}}return map;}}

3、SAXParserHandler代码

package org.jeecgframework.poi.xml;import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;import java.util.ArrayList;
import java.util.List;//xml解析
public class SAXParserHandler extends DefaultHandler {String value = null;List<String> rows = new ArrayList<>();int rowIndex = 0;int currentColumn = 0;public List<String> getRows() {return rows;}//用来标识解析开始@Overridepublic void startDocument() throws SAXException {super.startDocument();}//用来标识解析结束@Overridepublic void endDocument() throws SAXException {super.endDocument();}//解析xml元素@Overridepublic void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {super.startElement(uri, localName, qName, attributes);if (qName.equals("row")) {value = "";// 遇到新的行时,重置列号为0currentColumn = 0;} else if (qName.equals("c")) {// 获取列号String columnRef = attributes.getValue("r");if (columnRef != null) {currentColumn = parseColumnIndex(columnRef.replaceAll("[^A-Z]", ""));}}}@Overridepublic void endElement(String uri, String localName, String qName) throws SAXException {super.endElement(uri, localName, qName);if (qName.equals("c")) {if (value != null && value.contains("DISPIMG")) {value = value.substring(value.lastIndexOf("DISPIMG(")).replace("DISPIMG(\"", "");value = value.substring(0, value.indexOf("\""));
//                rows.add(rowIndex, value);rows.add(rowIndex + "_" + currentColumn + ":" + value);} else {
//                rows.add(rowIndex, null);rows.add(rowIndex + "_" + currentColumn + ":null");}value = "";}else if (qName.equals("row")) {rowIndex++;}}@Overridepublic void characters(char[] ch, int start, int length) throws SAXException {super.characters(ch, start, length);value += new String(ch, start, length);}// 解析列号private int parseColumnIndex(String columnRef) {int result = 0;for (int i = 0; i < columnRef.length(); i++) {result = result * 26 + (columnRef.charAt(i) - 'A' + 1);}return result - 1;}
}

相关文章:

jeecg导入excel 含图片(嵌入式,浮动式)

jeecgboot的excel导入 含图片&#xff08;嵌入式&#xff0c;浮动式&#xff09; 一、啰嗦二、准备三、 代码1、代码&#xff08;修改覆写的ExcelImportServer&#xff09;2、代码&#xff08;修改覆写的PoiPublicUtil&#xff09;3、代码&#xff08;新增类SAXParserHandler&a…...

GPT-5 一年半后发布?对此你有何期待?

GPT-5 一年半后发布&#xff1f;对此你有何期待&#xff1f; IT之家6月22日消息&#xff0c;在美国达特茅斯工程学院周四公布的采访中&#xff0c;OpenAI首席技术官米拉穆拉蒂被问及GPT-5是否会在明年发布&#xff0c;给出了肯定答案并表示将在一年半后发布。此外&#xff0c;…...

SHELL脚本学习(十二)sed进阶

一、多行命令 概述 sed 编辑器的基础命令都是对一行文本进行操作。如果要处理的数据分布在多行中&#xff0c;sed基础命令是没办法处理的。 幸运的是&#xff0c;sed编辑器的设计人员已经考虑了这个问题的解决方案。sed编辑器提供了3个处理多行文本的特殊命令。 命令描述N加…...

【python】一篇文零基础到入门:快来玩吧~

本笔记材料源于&#xff1a; PyCharm | 创建你的第一个项目_哔哩哔哩_bilibili Python 语法及入门 &#xff08;超全超详细&#xff09; 专为Python零基础 一篇博客让你完全掌握Python语法-CSDN博客 0为什么安装python和pycharm&#xff1f; 不同于c&#xff0c;c&#xff0…...

Python武器库开发-武器库篇之Thinkphp5 SQL注入漏洞(六十六)

Python武器库开发-武器库篇之Thinkphp5 SQL注入漏洞&#xff08;六十六&#xff09; 漏洞环境搭建 这里我们使用Kali虚拟机安装docker并搭建vulhub靶场来进行ThinkPHP漏洞环境的安装&#xff0c;我们进入 ThinkPHP漏洞环境&#xff0c;可以 cd ThinkPHP&#xff0c;然后通过 …...

2024.6.28刷题记录

目录 一、13. 罗马数字转整数 贪心 二、16. 最接近的三数之和 排序指针 三、17. 电话号码的字母组合 dfs&#xff08;深度优先搜索&#xff09; 四、19. 删除链表的倒数第 N 个结点 1.模拟 2.前后同步指针 五、20. 有效的括号 栈 六、21. 合并两个有序链表 1.递归 …...

柔性数组(flexible array)

柔性数组从C99开始支持使用 1.柔性数组的概念 概念&#xff1a; 结构体中&#xff0c;结构体最后一个元素允许是未知大小的数组&#xff0c;这就叫[柔性数组]的成员 struct S {int n;char arr[]; //数组大小未知(柔性数组成员) }; 柔性数组的特点&#xff1a; 结构体中柔性…...

服务器配置路由

translator 在Linux系统中&#xff0c;通过ip route add命令添加的路由规则通常不会永久保存&#xff0c;它们只会在当前会话中生效。当系统重新启动后&#xff0c;这些临时添加的路由规则会丢失。 要求在开关机之后仍然保留这条路由&#xff0c;需要将路由规则永久保存。在大多…...

老生常谈问题之什么是缓存穿透、缓存击穿、缓存雪崩?举个例子你就彻底懂了!!

老生常谈问题之什么是缓存穿透、缓存击穿、缓存雪崩&#xff1f;举个例子你就彻底懂了&#xff01;&#xff01; 缓存穿透发生场景解决方案 缓存击穿解决方案 缓存雪崩发生场景解决方案 总结三者区分三者原因三者解决方案 想象一下&#xff0c;你开了一家便利店&#xff0c;店里…...

[code snippet] 生成随机大文件

[code snippet] 生成随机大文件 一个无聊的测试代码&#xff0c;因为要测试大文件的网络传输&#xff0c;就写了一个随机大文件生成脚本&#xff0c;做个备份。 基本上都是 GPT 生成的&#xff0c;哈哈。 C# 代码 namespace ConsolePlayground;internal class BigFileGenera…...

计算机网路面试HTTP篇三

HTTPS RSA 握手解析 我前面讲&#xff0c;简单给大家介绍了的 HTTPS 握手过程&#xff0c;但是还不够细&#xff01; 只讲了比较基础的部分&#xff0c;所以这次我们再来深入一下 HTTPS&#xff0c;用实战抓包的方式&#xff0c;带大家再来窥探一次 HTTPS。 对于还不知道对称…...

如何不改变 PostgreSQL 列类型#PG培训

开发应用程序并在其背后操作数据库集群时&#xff0c;会遇到一个意想不到的问题是实践与理论、开发环境与生产之间的差异。这种不匹配的一个完美例子就是更改列类型。 #PG考试#postgresql培训#postgresql考试#postgresql认证 关于如何在 PostgreSQL&#xff08;以及其他符合 SQ…...

RocketMQ快速入门:事务消息原理及实现(十)

目录 0. 引言1. 原理2. 事务消息的实现2.1 java client实现&#xff08;适用于spring框架&#xff09;2.2 springboot实现 3. 总结 0. 引言 rocketmq 的一大特性就是支持事务性消息&#xff0c;这在诸多场景中有所应用。在之前的文章中我们已经讲解过事务消息的使用&#xff0…...

Kotlin设计模式:深入理解桥接模式

Kotlin设计模式&#xff1a;深入理解桥接模式 在软件开发中&#xff0c;随着系统需求的不断增长和变化&#xff0c;类的职责可能会变得越来越复杂&#xff0c;导致代码难以维护和扩展。桥接模式&#xff08;Bridge Pattern&#xff09;是一种结构型设计模式&#xff0c;它通过…...

常用MQ消息中间件Kafka、ZeroMQ和RabbitMQ对比及RabbitMQ详解

1、概述 在现代的分布式系统和实时数据处理领域&#xff0c;消息中间件扮演着关键的角色&#xff0c;用于解决应用程序之间的通信和数据传递的挑战。在众多的消息中间件解决方案中&#xff0c;Kafka、ZeroMQ和RabbitMQ 是备受关注和广泛应用的代表性系统。它们各自具有独特的特…...

【UE5.3】笔记6-第一个简单小游戏

打砖块小游戏&#xff1a; 1、制造一面砖块组成的墙 在关卡中放置一个cube&#xff0c;放这地面上&#xff0c;将其转换成蓝图类,改名BP_Cube&#xff0c;更换砖块的贴图&#xff0c;按住alt键进行拷贝&#xff0c;堆出一面墙&#xff0c;复制出来的会很多&#xff0c;全选移动…...

LeetCode---402周赛

题目列表 3184. 构成整天的下标对数目 I 3185. 构成整天的下标对数目 II 3186. 施咒的最大总伤害 3187. 数组中的峰值 一、构成整天的下标对数目 I & II 可以直接二重for循环暴力遍历出所有的下标对&#xff0c;然后统计符合条件的下标对数目返回。代码如下 class So…...

循环冗余校验

循环冗余校验&#xff08;Cyclic Redundancy Check&#xff0c;简称CRC&#xff09;是一种广泛使用的错误检测编码技术&#xff0c;用于检测数据在传输或存储过程中是否发生错误。CRC通过在数据后面添加一个校验值&#xff08;通常称为CRC码或CRC校验和&#xff09;来实现错误检…...

resample sensor

resample sensor 的一个问题。 背景: 项目要求&#xff0c;发送多个数据到 sensor-hal 上去&#xff0c;发现无论怎样&#xff0c;在 sensor-hal 上都 只有一个数据。 resample sensor 是重新采样&#xff0c;这个怎么理解的&#xff0c;我的理解是&#xff1a; 假设 sensor 采…...

【Linux】多线程的相关知识点

一、线程安全 1.1 可重入 VS 线程安全 1.1.1 概念 线程安全&#xff1a;多个线程并发执行同一段代码时&#xff0c;不会出现不同的结果。常见对全局变量或者静态变量进行操作&#xff0c;并且没有锁的保护的情况下&#xff0c;会出现问题。重入&#xff1a;同一个函数被不同…...

Java反射详解

Java反射 一.什么是反射 我们使用的一些像框架&#xff0c;tomcat&#xff0c;或者一些其他的组件(jackson 对象–>json)。他们可以做到给他什么类名&#xff0c;就可以创建给定类的对象&#xff0c;并调用该对象的方法和属性。这是如何做到的&#xff1f; 当他们加载我们…...

Spring Boot与Apache Kafka集成的深度指南

Spring Boot与Apache Kafka集成的深度指南 大家好&#xff0c;我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编&#xff0c;也是冬天不穿秋裤&#xff0c;天冷也要风度的程序猿&#xff01; 在现代分布式系统中&#xff0c;消息队列的作用愈发重要&#xff0…...

甄选版“论软件系统架构评估”,软考高级论文,系统架构设计师论文

论文真题 对于软件系统,尤其是大规模的复杂软件系统来说,软件的系统架构对于确保最终系统的质量具有十分重要的意义,不恰当的系统架构将给项目开发带来高昂的代价和难以避免的灾难。对一个系统架构进行评估,是为了:分析现有架构存在的潜在风险,检验设计中提出的质量需求,…...

uniapp开发企业微信内部应用

最近一直忙着开发项目&#xff0c;终于1.0版本开发完成&#xff0c;抽时间自己总结下在项目开发中遇到的技术点。此次项目属于自研产品&#xff0c;公司扩展业务&#xff0c;需要在企业微信中开发内部应用。因为工作中使用的是钉钉&#xff0c;很少使用企业微信&#xff0c;对于…...

0122__linux之eventfd理解

linux之eventfd理解-CSDN博客 Linux fd 系列 — eventfd 是什么&#xff1f;-CSDN博客...

数学建模 —— 查找数据

目录 百度搜索技巧 完全匹配搜索&#xff1a;查询词的外边加上双引号“ ” 标题必含关键词&#xff1a;查询词前加上intitle: 搜索文档&#xff1a;空格再输入filetype:文件格式 去掉不想要的&#xff1a;查询词后面加空格后加减号与关键字 知网查文献 先看知网的硕博士…...

合并有序链表

合并有序链表 图解代码如下 图解 虽然很复杂&#xff0c;但能够很好的理解怎么使用链表&#xff0c;以及对链表的指针类理解 代码如下 Node* merge_list_two_pointer(List& list1, List& list2) {Node* new_head1 list1.head;Node* new_head2 list2.head;Node* s…...

【SpringBoot Web框架实战教程】05 Spring Boot 使用 JdbcTemplate 操作数据库

不积跬步&#xff0c;无以至千里&#xff1b;不积小流&#xff0c;无以成江海。大家好&#xff0c;我是闲鹤&#xff0c;微信&#xff1a;xxh_1459&#xff0c;十多年开发、架构经验&#xff0c;先后在华为、迅雷服役过&#xff0c;也在高校从事教学3年&#xff1b;目前已创业了…...

Spark基于DPU的Native引擎算子卸载方案

1.背景介绍 Apache Spark&#xff08;以下简称Spark&#xff09;是一个开源的分布式计算框架&#xff0c;由UC Berkeley AMP Lab开发&#xff0c;可用于批处理、交互式查询&#xff08;Spark SQL&#xff09;、实时流处理&#xff08;Spark Streaming&#xff09;、机器学习&a…...

Mini2440 start.s 修改支持串口输出,方便调试 (四)

经常会遇到点板子的时候&#xff0c;板子没有任何反应&#xff01;怎么知道板子有没有在正常启动&#xff0c;在uboot阶段 start.s 中加入串口打印信息是很有必要的&#xff01; 输出串口信息 ***UART:mini-2440-uBoot*** ***UART:mini-2440-uBoot*** ***UART:mini-2440-uBoo…...

【教程】几种不同的RBF神经网络

本站原创文章&#xff0c;转载请说明来自《老饼讲解-机器学习》www.bbbdata.com 目录 一、经典RBF神经网络1.1.经典径向基神经网络是什么1.2.经典径向基神经网络-代码与示例 二、广义回归神经网络GRNN2.1.广义回归神经网络是什么2.2.广义回归神经网络是什么-代码与示例 三、概率…...

【Liunx-后端开发软件安装】Liunx安装FDFS并整合nginx

【Liunx-后端开发软件安装】Liunx安装nacos 文章中涉及的相关fdfs相关软件安装包请点击下载&#xff1a; https://download.csdn.net/download/weixin_49051190/89471122 一、简介 FastDFS是一个开源的轻量级分布式文件系统&#xff0c;它对文件进行管理&#xff0c;功能包括…...

【Java笔记】Flyway数据库管理工具的基本原理

文章目录 1. 工作流程2. 版本号校验算法3. 锁机制3.1 为什么数据库管理工具需要锁3.2 flyway的锁机制 Reference 最近实习做的几个项目都用到了Flyway来做数据库的版本管理&#xff0c;顺便了解了下基本原理&#xff0c;做个记录。 详细的使用就不写了&#xff0c;网上教程很多…...

国际数字影像产业园创业培训,全面提升创业能力!

国际数字影像产业园作为数字影像产业的创新高地&#xff0c;致力于提供全面的创业支持服务。其中&#xff0c;创业培训作为重要的组成部分&#xff0c;旨在通过系统的课程设置和专业的讲师团队&#xff0c;为创业者提供从基础到进阶的全方位指导&#xff0c;帮助他们在数字影像…...

pyqt5 制作视频剪辑软件,切割视频

该软件用于切割视频&#xff0c;手动选取视频片段的起始帧和结束帧并保存为json文件。gui界面如下&#xff1a;包含快进、快退、暂停等功能&#xff0c; 代码如下&#xff1a; # codingUTF-8 """ theme: pyqt5实现动作起始帧和结束帧的定位&#xff0c;将定位到…...

VUE----通过nvm管理node版本

使用 NVM&#xff08;Node Version Manager&#xff09;来管理和切换 Node.js 版本是一个很好的选择。以下是在 苹果电脑macos系统 上使用 NVM 安装和切换 Node.js 版本的步骤&#xff1a; 1. 安装 NVM 如果你还没有安装 NVM&#xff0c;可以按照以下步骤进行安装&#xff1a…...

R语言进行字符的替换和删减gsub,substr函数

目录 R语言读文件“-“变成“.“ 提取列字符前几个 提取列字符末尾几个 进行字母替换 paste0函数使用 长宽数据转换 R语言读文件“-“变成“.“ R语言读文件“-“变成“.“_r语言 列名中的-变成了点-CSDN博客 怎样将"."还原为"-" rm(list = ls()…...

2024年6月27日,欧盟REACH法规新增第31批1项SVHC高关注物质

ECHA公布第31批1项SVHC&#xff0c;物质已增至241项 2024年6月27日&#xff0c;ECHA公布第31批1项SVHC&#xff0c;总数达241项。新增物质未包括磷酸三苯酯&#xff0c;仍在评议中。REACH法规要求SVHC含量超0.1%需告知下游&#xff0c;出口超1吨须通报ECHA。SCIP通报要求SVHC含…...

高通410-linux棒子设置网络驱动

1.首先打开设备管理器 2.看到其他设备下的RNDIS&#xff0c;右键更新驱动程序 3.点击浏览我的电脑… 最后一个...

PostgreSQL的系统视图pg_stat_archiver

PostgreSQL的系统视图pg_stat_archiver 在 PostgreSQL 数据库中&#xff0c;pg_stat_archiver 视图提供了关于归档进程&#xff08;archiver process&#xff09;的统计信息。归档进程负责将 WAL&#xff08;Write-Ahead Logging&#xff09;日志文件复制到归档存储&#xff0…...

【D3.js in Action 3 精译】第一部分 D3.js 基础知识

第一部分 D3.js 基础知识 欢迎来到 D3.js 的世界&#xff01;可能您已经迫不及待想要构建令人惊叹的数据可视化项目了。我们保证&#xff0c;这一目标很快就能达成&#xff01;但首先&#xff0c;我们必须确保您已经掌握了 D3.js 的基础知识。这一部分提到的概念将会在您后续的…...

面试经验分享 | 渗透测试工程师(实习岗)

所面试的公司&#xff1a;某安全厂商 所在城市&#xff1a;南京 面试职位&#xff1a;渗透测试工程师实习岗位 面试过程&#xff1a; 腾讯会议&#xff08;视频&#xff09; 面试过程&#xff1a;整体流程就是自我介绍加上一些问题问题balabalabala。。。由于面的岗位是渗透…...

STM32 IWDG(独立看门狗)

1 IWDG简介 STM32有两个看门狗&#xff1a;一个是独立看门狗&#xff08;IWDG&#xff09;&#xff0c;另外一个是窗口看门狗。独立看门狗也称宠物狗&#xff0c;窗口看门狗也称警犬。本文主要分析独立看门狗的功能和它的应用。 独立看门狗用通俗一点的话来解释就是一个12位的…...

ios swift5 获取wifi列表

参考博客&#xff1a; iOS之Wifi开发探究 - 稀土掘金 iOS 无法获取 WiFi 列表&#xff1f;一定是因为你不知道这个框架 - 稀土掘金 iOS获取Wifi列表详解 - 简书...

回溯法c++学习 解决八皇后问题

使用回溯法解决八皇后问题 八皇后问题是一个以国际象棋为背景的问题&#xff1a;如何能够在88 的国际象棋棋盘上放置八个皇后&#xff0c;使得任何一个皇后都无法直接吃掉其他的皇后&#xff1f;为了达到此目的&#xff0c;任两个皇后都不能处于同一条横行、纵行或斜线上。这…...

5. Spring IoCDI ★ ✔

5. Spring IoC&DI 1. IoC & DI ⼊⻔1.1 Spring 是什么&#xff1f;★ &#xff08;Spring 是包含了众多⼯具⽅法的 IoC 容器&#xff09;1.1.1 什么是容器&#xff1f;1.1.2 什么是 IoC&#xff1f;★ &#xff08;IoC: Inversion of Control (控制反转)&#xff09;总…...

数据库自动备份到gitee上,实现数据自动化备份

本人有个不太好的习惯&#xff0c;每次项目的数据库都是在线上创建&#xff0c;Navicat 连接线上数据库进行处理&#xff0c;最近有一个项目需要二次升级&#xff0c;发现老项目部署的服务器到期了&#xff0c;完蛋&#xff0c;数据库咩了&#xff01;&#xff01;&#xff01;…...

探索 Spring Cloud Gateway:构建微服务架构的关键一环

1. 简介 在当今的分布式系统中&#xff0c;微服务架构已经成为了一种流行的架构模式。在微服务架构中&#xff0c;服务被拆分为小型、可独立部署的服务单元&#xff0c;这些服务单元能够通过网络互相通信&#xff0c;形成一个整体的应用系统。然而&#xff0c;随着微服务数量的…...

P1114 “非常男女”计划最优解

原题地址 P1114 “非常男女”计划 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 代码题解 AC代码&#xff08;1&#xff09; 因为用的是级的算法&#xff0c;所以最后一个 了&#xff0c;这里使用特判来得到的&#xff0c;给你们放一下代码&#xff1a; #include <bi…...

C++ | Leetcode C++题解之第187题重复的DNA序列

题目&#xff1a; 题解&#xff1a; class Solution {const int L 10;unordered_map<char, int> bin {{A, 0}, {C, 1}, {G, 2}, {T, 3}}; public:vector<string> findRepeatedDnaSequences(string s) {vector<string> ans;int n s.length();if (n < L…...

在 Windows 上,使用 icacls 命令让apache 用户有权访问

调试免费云服务器&#xff0c;三丰云&#xff0c;用户权限过程。 在 Windows 上&#xff0c;icacls 命令是一个非常强大的工具&#xff0c;用于修改文件和目录的权限。然而&#xff0c;需要注意的是&#xff0c;Windows 默认的 Web 服务器&#xff08;如 IIS&#xff09;通常运…...

el-config-provider在Vue3中自定义命名空间实现

一、场景 子应用使用微应用(qiankun)方式嵌入主应用时&#xff0c;如果主应用和子应用ElementUI版本不一致&#xff0c;可能会出现样式问题 二、实现 1、引入依赖sass、sass-loader npm install sass npm install sass-loader 2、创建element.scss 在src下创建/style/ele…...

Linux驱动开发实战宝典:设备模型、模块编程、I2C/SPI/USB外设精讲

摘要: 本文将带你走进 Linux 驱动开发的世界,从设备驱动模型、内核模块开发基础开始,逐步深入 I2C、SPI、USB 等常用外设的驱动编写,结合实际案例,助你掌握 Linux 驱动开发技能。 关键词: Linux 驱动,设备驱动模型,内核模块,I2C,SPI,USB 一、Linux 设备驱动模型 Li…...

【JS】期末复习题

一、选择题 1&#xff0e;下面四种标签哪种写法不正确&#xff08; D &#xff09;。 A&#xff0e;<html></html> B&#xff0e;<Html></Html> C&#xff0e;<HTML></HTML> D&#xff0e;<html><h…...

竞赛 深度学习 python opencv 火焰检测识别

文章目录 0 前言1 基于YOLO的火焰检测与识别2 课题背景3 卷积神经网络3.1 卷积层3.2 池化层3.3 激活函数&#xff1a;3.4 全连接层3.5 使用tensorflow中keras模块实现卷积神经网络 4 YOLOV54.1 网络架构图4.2 输入端4.3 基准网络4.4 Neck网络4.5 Head输出层 5 数据集准备5.1 数…...

搜索型数据库的技术发展历程与趋势前瞻

概述 随着数字科技的飞速发展和信息量的爆炸性增长&#xff0c;搜索引擎已成为我们获取信息的首选途径之一&#xff0c;典型的代表厂商如 Google。然而&#xff0c;随着用户需求的不断演变&#xff0c;传统的搜索技术已经无法满足人们对信息的实时性、个性化和多样性的需求。 …...

L3/L4产品准入和上路,9个联合体进入试点

6月4日,工业和信息化部、公安部、住房城乡建设部、交通运输部四部门联合宣布,按照《关于开展智能网联汽车准入和上路通行试点工作的通知》有关工作安排,经相关部门及专家初审和择优评审,已经确定了9个进入试点的联合体。2023年11月,上述四部门联合发布《关于开展智能网联汽…...

Java基础学习:深入解析Java中的位运算符

在Java中&#xff0c;位运算符用于对整数类型的值进行位运算。以下是Java中的位运算符&#xff1a; 位与(&)&#xff1a;两位都为1时&#xff0c;结果为1&#xff0c;否则为0。 位或(|)&#xff1a;两位中有1个为1&#xff0c;结果为1。 位非(~)&#xff1a;位的反&#…...

Flutter 中的 NestedScrollViewViewport 小部件:全面指南

Flutter 中的 NestedScrollViewViewport 小部件&#xff1a;全面指南 Flutter 是一个功能丰富的 UI 工具集&#xff0c;它提供了多种布局和控件来帮助开发者构建美观且功能强大的应用。在 Flutter 的滚动控件中&#xff0c;NestedScrollView 是一个特别的存在&#xff0c;它允…...

九章云极DataCanvas公司重磅亮相第七届数字中国建设峰会

近日&#xff0c;由国家发展改革委、国家数据局、国家网信办、科技部、国务院国资委、福建省人民政府共同主办的第七届数字中国建设峰会在福州盛大举行&#xff0c;九章云极DataCanvas公司重磅亮相峰会现场&#xff0c;深度展示智算中心建设核心成果及“算法算力”一体化AI智算…...

目标检测基础初步学习

目标检测&#xff08;Object Detection&#xff09; 目标检测任务说明 在动手学习深度学习中对目标检测任务有如下的描述。 图像分类任务中&#xff0c;我们假设图像中只有一个主要物体对象&#xff0c;我们只关注如何识别其类别。 然而&#xff0c;很多时候图像里有多个我们…...

你对仲裁裁决不服怎么办?我教你四个狠招!

你对仲裁裁决不服怎么办&#xff1f;我教你四个狠招&#xff01; 这个标题是什么意思呢&#xff1f;也就是说&#xff0c;当你&#xff08;或用人单位&#xff09;向劳动仲裁委提出仲裁申请后&#xff0c;但劳动仲裁结果没有维护你的权益&#xff0c;或者你不满意&#xff0c;…...