Merge remote-tracking branch 'origin/develop' into develop
This commit is contained in:
+284
-14
@@ -6,35 +6,40 @@ import com.alibaba.fastjson.JSONObject;
|
||||
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.renkang.consultation.async.AsyncExportService;
|
||||
import com.renkang.consultation.constant.ConsultationConstants;
|
||||
import com.renkang.consultation.dto.AccountDTO;
|
||||
import com.renkang.consultation.dto.ConDoctorDTO;
|
||||
import com.renkang.consultation.dto.DoctorAudioStatusDTO;
|
||||
import com.renkang.consultation.dto.DoctorJumpHolidayDTO;
|
||||
import com.renkang.consultation.entity.ConCostLog;
|
||||
import com.renkang.consultation.entity.ConDoctor;
|
||||
import com.renkang.consultation.entity.ConDoctorExAndUser;
|
||||
import com.renkang.consultation.entity.CondepartmentId;
|
||||
import com.renkang.consultation.entity.*;
|
||||
import com.renkang.consultation.mapper.ConResourceMapper;
|
||||
import com.renkang.consultation.mapper.ESConDoctorMapper;
|
||||
import com.renkang.consultation.service.IConDepartmentService;
|
||||
import com.renkang.consultation.service.IConDoctorService;
|
||||
import com.renkang.consultation.service.IConResourceService;
|
||||
import com.renkang.consultation.vo.AccountVO;
|
||||
import com.renkang.consultation.vo.ConDoctorExportVO;
|
||||
import com.renkang.consultation.vo.ConDoctorVO;
|
||||
import com.renkang.consultation.vo.ConServiceVO;
|
||||
import com.renkang.consultation.util.PicturesUtils;
|
||||
import com.renkang.consultation.vo.*;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.poi.ooxml.POIXMLDocumentPart;
|
||||
import org.apache.poi.ss.usermodel.*;
|
||||
import org.apache.poi.xssf.usermodel.*;
|
||||
import org.apache.shiro.authz.annotation.RequiresPermissions;
|
||||
import org.jeecg.common.api.vo.Result;
|
||||
import org.jeecg.common.aspect.annotation.AutoLog;
|
||||
import org.jeecg.common.constant.CommonConstant;
|
||||
import org.jeecg.common.system.api.ISysBaseAPI;
|
||||
import org.jeecg.common.system.base.controller.JeecgController;
|
||||
import org.jeecg.common.system.util.DictUtil;
|
||||
import org.jeecg.common.system.vo.DictModel;
|
||||
import org.jeecg.common.util.CheckPasswordUtil;
|
||||
import org.jeecg.common.util.MyUploadUtil;
|
||||
import org.jeecg.global.GlobalUtils;
|
||||
import org.jeecg.util.RSAEncryptUtils;
|
||||
import org.jeecgframework.poi.excel.ExcelImportUtil;
|
||||
import org.jeecgframework.poi.excel.entity.ImportParams;
|
||||
@@ -44,13 +49,13 @@ import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.*;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @Description: con_doctor
|
||||
@@ -72,6 +77,10 @@ public class ConDoctorController extends JeecgController<ConDoctor, IConDoctorSe
|
||||
private ESConDoctorMapper esConDoctorMapper;
|
||||
@Resource
|
||||
private AsyncExportService asyncExportService;
|
||||
@Autowired
|
||||
private ConResourceMapper conResourceMapper;
|
||||
@Autowired
|
||||
private DictUtil dictUtil;
|
||||
|
||||
/**
|
||||
* 分页列表查询
|
||||
@@ -445,5 +454,266 @@ public class ConDoctorController extends JeecgController<ConDoctor, IConDoctorSe
|
||||
// }
|
||||
// esConDoctorMapper.deleteById(id);
|
||||
// return Result.OK("出库成功!");
|
||||
// }
|
||||
|
||||
|
||||
@PostMapping("/initDoctor")
|
||||
public String initDoctor(@RequestParam("file") MultipartFile file,
|
||||
@RequestParam("token") String token,
|
||||
@RequestParam("urlPath") String urlPath) {
|
||||
if (file.isEmpty()) {
|
||||
return "上传文件为空";
|
||||
}
|
||||
PicturesUtils picturesUtils = new PicturesUtils();
|
||||
try {
|
||||
byte[] fileData = file.getBytes(); // 读取上传文件的字节流
|
||||
Map<Integer, PicturesUtils.PicturePosition> pictures = picturesUtils.getPicturesWithRow(fileData);
|
||||
|
||||
try (InputStream is = file.getInputStream();
|
||||
XSSFWorkbook workbook = new XSSFWorkbook(is)) {
|
||||
|
||||
XSSFSheet sheet = workbook.getSheetAt(0);
|
||||
|
||||
for (int rowIndex = 2; rowIndex <= sheet.getLastRowNum(); rowIndex++) {
|
||||
Row row = sheet.getRow(rowIndex);
|
||||
if (row == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ConDoctorExAndUser doctorExAndUser = new ConDoctorExAndUser();
|
||||
ConDoctorDoctorVO doctorVO = new ConDoctorDoctorVO();
|
||||
ConDoctorUserVO userVO = new ConDoctorUserVO();
|
||||
|
||||
String name = getCellStringValue(row.getCell(0));
|
||||
doctorVO.setDoctorName(name);
|
||||
String account = getCellStringValue(row.getCell(1));
|
||||
userVO.setUsername(name);
|
||||
String password = getCellStringValue(row.getCell(2));
|
||||
String g = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCmZfR/bA9X3vp86y1aEpvwzXJYKRRF1fLau2+05/ZtaITLpV8bhkmSf3neSy/Q9gAdvG75Fr73E+GWE+K5b0BpvIS1jDGo319+PpZR39SaZTKZ27XFXrosmJTZutN79t819HS1VseleunHAFgMVufE9U5jP6LGzl/wbkSy01GhzwIDAQAB";
|
||||
String cipherText = RSAEncryptUtils.encrypt1(password, g);
|
||||
|
||||
String key = RSAEncryptUtils.decrypt1(cipherText, CommonConstant.PRIVATE_KEY);
|
||||
String s = CheckPasswordUtil.checkPasswordRule(key);
|
||||
if (StrUtil.isNotBlank(s)) {
|
||||
return null;
|
||||
}
|
||||
userVO.setPassword(cipherText);
|
||||
|
||||
System.out.println("第" + (rowIndex + 1) + "行数据:姓名=" + name + ", 账号=" + account + ", 密码=" + password);
|
||||
|
||||
// 根据行号直接获取对应图片
|
||||
PicturesUtils.PicturePosition picPos = pictures.get(rowIndex);
|
||||
if (picPos != null) {
|
||||
XSSFPictureData xssfPictureData = picPos.getPictureData();
|
||||
String fileName = xssfPictureData.getPackagePart().getPartName().getName();
|
||||
System.out.println("图片文件名:" + fileName);
|
||||
|
||||
File imgFile = new File("D:\\" + fileName);
|
||||
File dir = imgFile.getParentFile();
|
||||
if (!dir.exists()) {
|
||||
dir.mkdirs();
|
||||
}
|
||||
try {
|
||||
Files.write(Paths.get(imgFile.getPath()), xssfPictureData.getData());
|
||||
// 调用之前写好的上传接口,传入token
|
||||
String url = uploadImage(imgFile, MyUploadUtil.TEMP_BIZ, token,urlPath);
|
||||
userVO.setAvatar(url);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
String resourceName = getCellStringValue(row.getCell(4));
|
||||
doctorVO.setResourceName(resourceName);
|
||||
List<ConResource> conResources = conResourceMapper.selectByResourceName(resourceName);
|
||||
if (conResources != null && !conResources.isEmpty()) {
|
||||
ConResource conResource = conResources.get(0);
|
||||
if (conResource != null) {
|
||||
doctorVO.setResourceId(conResource.getId());
|
||||
}
|
||||
}
|
||||
|
||||
String zc = getCellStringValue(row.getCell(6));
|
||||
List<DictModel> models = dictUtil.queryDictItemListByCode("z_doct_lev");
|
||||
DictModel dictModel = models.stream().filter(item -> item.getText().equals(zc)).findFirst().orElse(null);
|
||||
if (dictModel != null) {
|
||||
doctorVO.setDoctorJob(dictModel.getValue());
|
||||
}
|
||||
|
||||
doctorVO.setGoodAt(getCellStringValue(row.getCell(7)));
|
||||
doctorVO.setExperience(getCellStringValue(row.getCell(8)));
|
||||
String sex = getCellStringValue(row.getCell(9));
|
||||
userVO.setSex(Integer.valueOf(sex));
|
||||
} else {
|
||||
System.out.println("第" + (rowIndex + 1) + "行无对应图片");
|
||||
}
|
||||
doctorExAndUser.setConDoctor(doctorVO);
|
||||
doctorExAndUser.setSysUserModel(userVO);
|
||||
conDoctorService.saveDoctorUser(doctorExAndUser);
|
||||
|
||||
System.out.println(rowIndex);
|
||||
}
|
||||
return "处理成功";
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return "处理失败:" + e.getMessage();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 上传图片文件到指定接口,返回响应字符串(一般是json)。
|
||||
* @param file 头像文件
|
||||
* @param bizValue biz字段值,示例中固定为 "temp"
|
||||
* @param token x-access-token 请求头值
|
||||
* @return 服务端响应内容
|
||||
* @throws Exception 异常抛出
|
||||
*/
|
||||
private String uploadImage(File file, String bizValue, String token,String urlPath) throws Exception {
|
||||
String boundary = "----WebKitFormBoundaryGEKNMBfLirBXKE2d";
|
||||
String LINE_FEED = "\r\n";
|
||||
String charset = "UTF-8";
|
||||
|
||||
URL url = new URL(urlPath);
|
||||
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
|
||||
conn.setUseCaches(false);
|
||||
conn.setDoOutput(true);
|
||||
conn.setDoInput(true);
|
||||
conn.setRequestMethod("POST");
|
||||
conn.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);
|
||||
conn.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.0.0 Safari/537.36");
|
||||
conn.setRequestProperty("x-access-token", token);
|
||||
conn.setRequestProperty("x-requested-with", "XMLHttpRequest");
|
||||
|
||||
try (
|
||||
OutputStream outputStream = conn.getOutputStream();
|
||||
PrintWriter writer = new PrintWriter(new OutputStreamWriter(outputStream, charset), true);
|
||||
) {
|
||||
// 写 biz 字段
|
||||
writer.append("--").append(boundary).append(LINE_FEED);
|
||||
writer.append("Content-Disposition: form-data; name=\"biz\"").append(LINE_FEED);
|
||||
writer.append(LINE_FEED);
|
||||
writer.append(bizValue).append(LINE_FEED);
|
||||
writer.flush();
|
||||
|
||||
// 写文件字段
|
||||
String fileName = file.getName();
|
||||
String mimeType = Files.probeContentType(file.toPath());
|
||||
if (mimeType == null) {
|
||||
mimeType = "application/octet-stream";
|
||||
}
|
||||
writer.append("--").append(boundary).append(LINE_FEED);
|
||||
writer.append("Content-Disposition: form-data; name=\"file\"; filename=\"").append(fileName).append("\"").append(LINE_FEED);
|
||||
writer.append("Content-Type: ").append(mimeType).append(LINE_FEED);
|
||||
writer.append(LINE_FEED);
|
||||
writer.flush();
|
||||
|
||||
try (FileInputStream inputStream = new FileInputStream(file)) {
|
||||
byte[] buffer = new byte[4096];
|
||||
int bytesRead;
|
||||
while ((bytesRead = inputStream.read(buffer)) != -1) {
|
||||
outputStream.write(buffer, 0, bytesRead);
|
||||
}
|
||||
outputStream.flush();
|
||||
}
|
||||
|
||||
writer.append(LINE_FEED);
|
||||
writer.flush();
|
||||
|
||||
// 结尾
|
||||
writer.append("--").append(boundary).append("--").append(LINE_FEED);
|
||||
writer.flush();
|
||||
}
|
||||
|
||||
int status = conn.getResponseCode();
|
||||
InputStream responseStream = (status >= 200 && status < 300) ? conn.getInputStream() : conn.getErrorStream();
|
||||
|
||||
try (BufferedReader reader = new BufferedReader(new InputStreamReader(responseStream, charset))) {
|
||||
StringBuilder response = new StringBuilder();
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
response.append(line);
|
||||
}
|
||||
|
||||
// 解析json,提取result.url
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
JsonNode rootNode = mapper.readTree(response.toString());
|
||||
if (rootNode.path("success").asBoolean(false)) {
|
||||
JsonNode urlNode = rootNode.path("result").path("url");
|
||||
if (!urlNode.isMissingNode()) {
|
||||
return urlNode.asText();
|
||||
}
|
||||
}
|
||||
// 如果失败或无url,返回完整响应或空
|
||||
return "";
|
||||
} finally {
|
||||
conn.disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
private String getCellStringValue(Cell cell) {
|
||||
if (cell == null) {
|
||||
return "";
|
||||
}
|
||||
cell.setCellType(CellType.STRING);
|
||||
return cell.getStringCellValue().trim();
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
PicturesUtils picturesUtils = new PicturesUtils();
|
||||
byte[] fileData = picturesUtils.getFileStream(new File("C:\\Users\\Huawei\\Desktop\\专家库.xlsm"));
|
||||
Map<Integer, PicturesUtils.PicturePosition> pictures = picturesUtils.getPicturesWithRow(fileData);
|
||||
pictures.forEach((row, picturePosition) -> {
|
||||
System.out.println("图片所在行号(从0开始):" + row);
|
||||
XSSFPictureData pictureData = picturePosition.getPictureData();
|
||||
String fileName = pictureData.getPackagePart().getPartName().getName();
|
||||
System.out.println("文件名:" + fileName);
|
||||
// 保存路径,注意转义反斜杠
|
||||
File file = new File("D:\\" + fileName);
|
||||
File dir = file.getParentFile();
|
||||
if (!dir.exists()) {
|
||||
dir.mkdirs();
|
||||
}
|
||||
try {
|
||||
Files.write(Paths.get(file.getPath()), pictureData.getData());
|
||||
System.out.println("图片保存成功,路径:" + file.getPath());
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// public static void main(String[] args) {
|
||||
// String filePath = "C:\\Users\\Huawei\\Desktop\\专家库.xlsm";
|
||||
//
|
||||
// try (FileInputStream fis = new FileInputStream(filePath);
|
||||
// XSSFWorkbook workbook = new XSSFWorkbook(fis)) {
|
||||
//
|
||||
// XSSFSheet sheet = workbook.getSheetAt(0);
|
||||
//
|
||||
// XSSFDrawing drawing = sheet.getDrawingPatriarch();
|
||||
// if (drawing == null) {
|
||||
// System.out.println("该sheet没有图片");
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// List<XSSFShape> shapes = drawing.getShapes();
|
||||
// for (XSSFShape shape : shapes) {
|
||||
// if (shape instanceof XSSFPicture) {
|
||||
// XSSFPicture picture = (XSSFPicture) shape;
|
||||
// XSSFClientAnchor anchor = picture.getPreferredSize();
|
||||
//
|
||||
// int row = anchor.getRow1(); // 图片所在的起始行号(从0开始)
|
||||
// int col = anchor.getCol1(); // 图片所在的起始列号
|
||||
//
|
||||
// String fileName = picture.getPictureData().getPackagePart().getPartName().getName();
|
||||
// System.out.println("图片对应行:" + (row + 1) + ",列:" + (col + 1) + ",文件名:" + fileName);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// } catch (Exception e) {
|
||||
// e.printStackTrace();
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
+370
@@ -0,0 +1,370 @@
|
||||
package com.renkang.consultation.util;
|
||||
|
||||
import cn.hutool.json.JSONArray;
|
||||
import cn.hutool.json.JSONObject;
|
||||
import cn.hutool.json.XML;
|
||||
import lombok.Data;
|
||||
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.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
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 PicturesUtils {
|
||||
|
||||
public static void main(String[] args) {
|
||||
PicturesUtils picturesUtils = new PicturesUtils();
|
||||
byte[] fileData = picturesUtils.getFileStream(new File("你的文件路径"));
|
||||
Map<String, XSSFPictureData> pictures = picturesUtils.getPictures(fileData);
|
||||
pictures.forEach((id, xssfPictureData) -> {
|
||||
System.out.println("id:" + id);
|
||||
String fileName = xssfPictureData.getPackagePart().getPartName().getName();
|
||||
System.out.println("fileName:" + fileName);
|
||||
File file = new File("C:\\Users\\XXX\\Desktop\\" + fileName);
|
||||
File dir = file.getParentFile();
|
||||
dir.mkdirs();
|
||||
try {
|
||||
Files.write(Paths.get(file.getPath()), xssfPictureData.getData());
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取浮动图片,以 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 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 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<>();
|
||||
}
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class PicturePosition {
|
||||
private XSSFPictureData pictureData;
|
||||
private int row;
|
||||
private int col;
|
||||
|
||||
public PicturePosition(XSSFPictureData pictureData, int row, int col) {
|
||||
this.pictureData = pictureData;
|
||||
this.row = row;
|
||||
this.col = col;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public Map<Integer, PicturePosition> getPicturesWithRow(byte[] data) {
|
||||
Map<Integer, PicturePosition> pictureMap = new HashMap<>();
|
||||
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()) {
|
||||
XSSFSheet sheet = (XSSFSheet) sheetIterator.next();
|
||||
Map<Integer, PicturePosition> floatingPics = getFloatingPicturesWithRow(sheet);
|
||||
pictureMap.putAll(floatingPics);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
// 处理异常
|
||||
}
|
||||
return pictureMap;
|
||||
}
|
||||
|
||||
public static Map<Integer, PicturePosition> getFloatingPicturesWithRow(XSSFSheet xssfSheet) {
|
||||
Map<Integer, PicturePosition> map = 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();
|
||||
int row = anchor.getRow1();
|
||||
int col = anchor.getCol1();
|
||||
map.put(row, new PicturePosition(picture.getPictureData(), row, col));
|
||||
}
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理 Zip 文件中的条目,更新图片配置信息。
|
||||
*
|
||||
* @param stream Zip 输入流
|
||||
* @return 配置信息的 map
|
||||
* @throws IOException
|
||||
*/
|
||||
private 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 void processCellImages(ZipInputStream zipInputStream, Map<String, String> mapConfig) throws IOException {
|
||||
String content = IOUtils.toString(zipInputStream, StandardCharsets.UTF_8);
|
||||
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 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 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 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 Map<String, String> processCellImagesRels(ZipInputStream zipInputStream, Map<String, String> mapConfig) throws IOException {
|
||||
String content = IOUtils.toString(zipInputStream, StandardCharsets.UTF_8);
|
||||
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; // Java 8 显式类型转换
|
||||
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 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param file 数据文件
|
||||
* @return {@link byte[]}
|
||||
* @description
|
||||
* @author bianhl
|
||||
* @date 2024/4/26 13:52
|
||||
*/
|
||||
public byte[] getFileStream(File file) {
|
||||
try (InputStream inputStream = new FileInputStream(file)) {
|
||||
// 创建 ByteArrayOutputStream 来暂存流数据
|
||||
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
|
||||
// 将 inputStream 读取到 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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -41,6 +41,7 @@ import java.util.List;
|
||||
@Slf4j
|
||||
public class MyUploadUtil {
|
||||
public final static String IMPORT_BIZ = "import";
|
||||
public final static String TEMP_BIZ = "temp";
|
||||
public final static String EXPORT_BIZ = "export";
|
||||
private static String muUrl;
|
||||
private static String muToken;
|
||||
|
||||
Reference in New Issue
Block a user