package com.jiashi.service; import com.google.gson.Gson; import com.jiashi.CommonResult; import com.jiashi.FilePathUtil; import com.jiashi.FileUploader; import com.jiashi.dao.DataQuery; import lombok.extern.slf4j.Slf4j; import net.coobird.thumbnailator.Thumbnails; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.springframework.util.CollectionUtils; import javax.annotation.PostConstruct; import javax.imageio.ImageIO; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.Date; import java.util.List; import java.util.Map; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import java.util.function.Function; import java.util.stream.Collectors; @Component @Slf4j public class UpdateService { @Autowired private DataQuery dataQuery; public List updateData() { List cardInfos = dataQuery.dateQuery(); dataQuery.updateBatchState(cardInfos, 1); return cardInfos; } //state 状态标识。0 未开始, 1, 正在进行, 3. 已经成功。 4. 失败。5. 不需要上传的 @PostConstruct public void upload() { log.info("联众同步数据启动>>>>>>>>>>>>>>>>>>>>"); String syncDir = FilePathUtil.currentPath() + File.separator + "lianzhong-sync"; FilePathUtil.mkdirs(syncDir); ExecutorService patientExecutors = Executors.newFixedThreadPool(10); ExecutorService fileExecutor = Executors.newFixedThreadPool(90); try { while (true) { List cardInfos = this.updateData(); if (!CollectionUtils.isEmpty(cardInfos)) { List patientFutures = new ArrayList<>(); for (CardInfo cardInfo : cardInfos) { String picDir = syncDir + File.separator + cardInfo.getId(); FilePathUtil.mkdirs(picDir); Future patientFuture = patientExecutors.submit(() -> { try { List pictures = dataQuery.getPictures(cardInfo.getId()); if (CollectionUtils.isEmpty(pictures)) { //如果是空的则不同步 dataQuery.updateBatchState(cardInfo, 5); FilePathUtil.deleteDir(picDir); return; } String lianZhongDir = findLianZhongDir(cardInfo); if (lianZhongDir == null) { //失败,说明原因 dataQuery.updateBatchState(cardInfo, 2, "未找到联众数据文件夹!"); FilePathUtil.deleteDir(picDir); return; } dataQuery.updatePicPath(cardInfo, lianZhongDir); List fileFutures = new ArrayList<>(); for (Picture picture : pictures) { Future fileFuture = fileExecutor.submit(() -> { String tifFilePath = lianZhongDir + File.separator + removeFileExtension(picture.getPicname()) + ".tif"; File tifFile = new File(tifFilePath); if (tifFile.exists()) { try { BufferedImage read = ImageIO.read(tifFile); Thumbnails.of(read) .scale(1) .outputFormat("jpg") .rotate(picture.getRotatedegree()) .toFile(picDir + File.separator + removeFileExtension(picture.getPicname()) + ".jpg"); read.flush(); } catch (IOException e) { throw new RuntimeException(e); } } }); fileFutures.add(fileFuture); } for (Future future : fileFutures) { try { future.get(); } catch (InterruptedException | ExecutionException e) { throw new RuntimeException(e); } } LianZhongUploadInfo.PatientInfo patientInfo = convert(cardInfo); List fileInfos = new ArrayList<>(); List faultFileNames = new ArrayList<>(); List files = new ArrayList<>(); for (Picture picture : pictures) { File pictureFile = new File(picDir + File.separator + removeFileExtension(picture.getPicname()) + ".jpg"); if (!pictureFile.exists()) { faultFileNames.add(picture.getPicname()); continue; } files.add(pictureFile); LianZhongUploadInfo.FileInfo fileInfo=new LianZhongUploadInfo.FileInfo(); fileInfo.setFileTitle(picture.getPicname()); fileInfo.setUploadFileName(pictureFile.getName()); fileInfo.setAssortId(picture.getPickind()); // todo 应该有个排序 fileInfo.setSort(0); fileInfos.add(fileInfo); } if (files.isEmpty()) { dataQuery.updateBatchState(cardInfo, 2,"未获取到图片!"); // 删除文件 FilePathUtil.deleteDir(picDir); return; } LianZhongUploadInfo uploadInfo = new LianZhongUploadInfo(); uploadInfo.setPatientInfo(patientInfo); uploadInfo.setFileInfos(fileInfos); try { Map fileInfoMap = fileInfos.stream() .collect(Collectors.toMap(LianZhongUploadInfo.FileInfo::getUploadFileName, Function.identity())); boolean success = true; // 上传 int totalSize = files.size(); int batchSize = 500; if (totalSize > batchSize) { for (int i = 0; i < totalSize; i += batchSize) { ArrayList batch = new ArrayList<>(); List uploadFileInfoList = new ArrayList<>(); // 计算当前批次的结束索引 int end = Math.min(i + batchSize, totalSize); for (int j = i; j < end; j++) { batch.add(files.get(j)); uploadFileInfoList.add(fileInfoMap.get(files.get(j).getName())); } uploadInfo.setFileInfos(uploadFileInfoList); // 额外的表单字段参数 List params = new ArrayList<>(); String s = new Gson().toJson(uploadInfo); params.add(new FormField("uploadFileParams", s)); CommonResult commonResult = FileUploader.uploadFilesWithParams(batch, "http://192.168.161.102:9511/lianzhong/batchFileUploadJpg", params); boolean res = commonResult.getCode() == 0; success = success && res; } } else { // 额外的表单字段参数 List params = new ArrayList<>(); String s = new Gson().toJson(uploadInfo); params.add(new FormField("uploadFileParams", s)); CommonResult commonResult = FileUploader.uploadFilesWithParams(files, "http://192.168.161.102:9511/lianzhong/batchFileUploadJpg", params); success = commonResult.getCode() == 0; } if (success) { dataQuery.updateBatchState(cardInfo, 3); } else { dataQuery.updateBatchState(cardInfo, 2,"上传服务端出现异常!"); } } catch (Exception e) { dataQuery.updateBatchState(cardInfo, 2,e.getMessage()); log.error(e.getMessage(), e); } if (!faultFileNames.isEmpty()) { // 不完整 dataQuery.updateBatchState(cardInfo, 2,String.join(",",faultFileNames+" 无法转换jpg图片!")); } // 删除文件 FilePathUtil.deleteDir(picDir); }catch (Exception ex){ log.error(ex.getMessage(),ex); FilePathUtil.deleteDir(picDir); dataQuery.updateBatchState(cardInfo, 2,ex.getMessage()); } }); patientFutures.add(patientFuture); } for (Future future : patientFutures) { future.get(); } continue; } TimeUnit.SECONDS.sleep(300); } } catch (Exception ex) { log.error("联众同步数据异常:" + ex.getMessage(), ex); } } private LianZhongUploadInfo.PatientInfo convert(CardInfo cardInfo) { SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); LianZhongUploadInfo.PatientInfo patientInfo=new LianZhongUploadInfo.PatientInfo(); // todo 病案号 patientInfo.setInpatientNo(null); // todo 住院次数 patientInfo.setAdmissTimes(null); patientInfo.setName(cardInfo.getPatname()); // todo 年龄 patientInfo.setSex("") ; patientInfo.setSexName("") ; patientInfo.setAdmissDate(cardInfo.getIndate() == null ?null:sdf.format(cardInfo.getIndate())) ; patientInfo.setDisDate(cardInfo.getOutdate() == null ?null:sdf.format(cardInfo.getOutdate())); patientInfo.setAdmissDeptName(cardInfo.getIndeptname()) ; patientInfo.setDisDeptName(cardInfo.getOutdeptname()); patientInfo.setIdCard(cardInfo.getPatciticard()) ; patientInfo.setMainDiagCode(null) ; patientInfo.setMainDiagName(null) ; patientInfo.setMainOperateCode(null); patientInfo.setMainOperateName(null); return patientInfo; } private String findLianZhongDir(CardInfo cardInfo) { String gestno = cardInfo.getGestno(); String patno = cardInfo.getPatno(); Date outdate = cardInfo.getOutdate(); SimpleDateFormat yearSdf = new SimpleDateFormat("yyyy"); SimpleDateFormat yearMonthSdf = new SimpleDateFormat("yyyyMM"); SimpleDateFormat yearMonthDaySdf = new SimpleDateFormat("yyyyMMdd"); String yFormat = yearSdf.format(outdate); String ymFormat = yearMonthSdf.format(outdate); String ymdFormat = yearMonthDaySdf.format(outdate); List archiveDirs = Arrays.asList( "D:\\UnionNet\\ServerD", "D:\\UnionNet\\ServerD_ny", "D:\\UnionNet\\ServerDTemp", "G:\\UnionNet\\ServerD", "G:\\UnionNet\\ServerD_ny", "G:\\UnionNet\\ServerDTemp"); for (String archiveDir : archiveDirs) { String ymdDateDir = archiveDir + File.separator + yFormat + File.separator + ymFormat + File.separator + ymdFormat; File ymdDateDirFile = new File(ymdDateDir); if (!ymdDateDirFile.exists()) { continue; } File[] patPicDirs = ymdDateDirFile.listFiles(); if (patPicDirs != null && patPicDirs.length > 0) { for (File patPicDir : patPicDirs) { String dirName = patPicDir.getName(); String comparePart = dirName.substring(2).substring(0, 10); comparePart = removeLeadingZeros(comparePart); //TODO gestno 或者 patno 进行 识别 boolean match = comparePart.contains(removeLeadingZeros(patno)); if (match) { return patPicDir.getPath(); } } } } return null; } public static String removeLeadingZeros(String str) { if (str == null || str.isEmpty()) { return str; // 如果字符串为空或null,直接返回 } int index = 0; // 循环检查每个字符,直到找到不是'0'的字符 while (index < str.length() && str.charAt(index) == '0') { index++; } // 返回从第一个非'0'字符开始到字符串末尾的子字符串 return str.substring(index); } public static String removeFileExtension(String fileName) { // 检查文件名是否为空或没有后缀 if (fileName == null || !fileName.contains(".")) { return fileName; } // 找到最后一个'.'字符的位置 int lastDotIndex = fileName.lastIndexOf('.'); // 截取不包含后缀的部分 return fileName.substring(0, lastDotIndex); } }