You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
LianzhongCollect/src/main/java/com/jiashi/service/UpdateService.java

397 lines
19 KiB
Java

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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 org.springframework.util.StringUtils;
import javax.annotation.PostConstruct;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
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;
private Set<String> lianZhongPatPicDirs = new HashSet<>();
public List<CardInfo> updateData() {
List<CardInfo> cardInfos = dataQuery.dateQuery();
dataQuery.updateBatchState(cardInfos, 1);
return cardInfos;
}
//state 状态标识。0 未开始, 1 正在进行, 3. 已经成功。 4. 失败。5. 不需要上传的
@PostConstruct
public void upload() {
initLianZhongPatPicDir();
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<CardInfo> cardInfos = this.updateData();
if (!CollectionUtils.isEmpty(cardInfos)) {
List<Future> patientFutures = new ArrayList<>();
for (CardInfo cardInfo : cardInfos) {
String picDir = syncDir + File.separator + cardInfo.getId();
FilePathUtil.mkdirs(picDir);
Future patientFuture = patientExecutors.submit(() -> {
try {
List<Picture> 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<Future> 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<LianZhongUploadInfo.FileInfo> fileInfos = new ArrayList<>();
List<String> faultFileNames = new ArrayList<>();
List<File> 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());
fileInfo.setSort(picture.getPicno());
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<String, LianZhongUploadInfo.FileInfo> 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<File> batch = new ArrayList<>();
List<LianZhongUploadInfo.FileInfo> 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<FormField> params = new ArrayList<>();
String s = new Gson().toJson(uploadInfo);
params.add(new FormField("uploadFileParams", s));
CommonResult commonResult = FileUploader.uploadFilesWithParams(batch, "http://129.7.1.25:9511/lianzhong/batchFileUploadJpg", params);
boolean res = commonResult.getCode() == 0;
success = success && res;
}
} else {
// 额外的表单字段参数
List<FormField> params = new ArrayList<>();
String s = new Gson().toJson(uploadInfo);
params.add(new FormField("uploadFileParams", s));
CommonResult commonResult = FileUploader.uploadFilesWithParams(files, "http://129.7.1.25: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);
}
}
public static void main(String[] args) {
UpdateService updateService = new UpdateService();
System.out.println(new Gson().toJson(updateService.lianZhongPatPicDirs));
updateService.initLianZhongPatPicDir();
System.out.println(new Gson().toJson(updateService.lianZhongPatPicDirs));
}
private void initLianZhongPatPicDir() {
log.info(">>>>>>>>>>>>初始化联众患者文件目录");
String readFilePath = FilePathUtil.currentPath() + File.separator + "lianzhong-patpic-dir.txt";
File readFile = new File(readFilePath);
if (readFile.exists()) {
try (BufferedReader bufferedReader = new BufferedReader(new FileReader(readFile))) {
String line;
while ((line = bufferedReader.readLine()) != null) {
lianZhongPatPicDirs.add(line);
}
return;
} catch (Exception ex) {
log.error(">>>>>>>>>>>> 初始化联众患者文件目录读取存储文件错误!");
}
}
List<String> rootDirs = Arrays.asList("D:\\UnionNet\\ServerD", "D:\\UnionNet\\ServerD_ny", "D:\\UnionNet\\ServerDTemp",
"G:\\UnionNet\\ServerD", "G:\\UnionNet\\ServerD_ny", "G:\\UnionNet\\ServerDTemp");
for (String rootDir : rootDirs) {
File rootDirFile = new File(rootDir);
if (!rootDirFile.exists()) {
continue;
}
// 第一层 年 ,如果有,后面基本都会有
File[] level1 = rootDirFile.listFiles();
if (level1 == null || level1.length <= 0) {
continue;
}
for (File level1File : level1) {
// 第二层 年月
File[] level2 = level1File.listFiles();
if (level2 == null || level2.length <= 0) {
continue;
}
for (File level2File : level2) {
if (level2File.isDirectory()) {
// 第三层 年月日
File[] level3 = level2File.listFiles();
if (level3 == null || level3.length <= 0) {
continue;
}
for (File level3File : level3) {
if (level3File.isDirectory()) {
// 第四层,患者存放文件的最后一级目录
File[] level4 = level3File.listFiles();
if (level4 == null || level4.length <= 0) {
continue;
}
for (File level4File : level4) {
if (level4File.isDirectory()) {
lianZhongPatPicDirs.add(level4File.getPath());
}
}
}
}
}
}
}
}
if (!lianZhongPatPicDirs.isEmpty()) {
try (BufferedWriter writer = new BufferedWriter(new FileWriter(readFile));) {
for (String picDir : lianZhongPatPicDirs) {
writer.write(picDir);
writer.newLine();
}
} catch (Exception ex) {
log.error("持久化联众患者文件目录错误:" + ex.getMessage(), ex);
if (readFile.exists()) {
readFile.delete();
}
}
}
}
private LianZhongUploadInfo.PatientInfo convert(CardInfo cardInfo) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
LianZhongUploadInfo.PatientInfo patientInfo = new LianZhongUploadInfo.PatientInfo();
patientInfo.setInpatientNo(cardInfo.getPatno());
String gestno = cardInfo.getGestno();
// 123步设置住院次数
Integer admissTimes = cardInfo.getPatnum();
if (admissTimes == null && StringUtils.hasText(gestno)) {
try {
String admissTimesStr = removeLeadingZeros(gestno.substring(gestno.length() - 3));
admissTimes = Integer.valueOf(admissTimesStr);
} catch (Exception ex) {
log.error("无法解析gestno{} 当中的住院次数!", gestno);
}
}
// 没办法获取那就直接用出院的日期当住院次数
if (admissTimes == null) {
SimpleDateFormat sdf2 = new SimpleDateFormat("yyyyMMdd");
admissTimes = Integer.valueOf(sdf2.format(cardInfo.getOutdate()));
}
patientInfo.setAdmissTimes(admissTimes);
patientInfo.setAge(cardInfo.getPatage());
patientInfo.setName(cardInfo.getPatname());
patientInfo.setSex("1".equals(cardInfo.getPatsex()) ? "男" : "女");
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();
for (String lianZhongPatPicDir : lianZhongPatPicDirs) {
String dirName = new File(lianZhongPatPicDir).getName();
String comparePart = dirName.substring(2).substring(0, 10);
comparePart = removeLeadingZeros(comparePart);
// gestno 或者 patno 进行 识别
if (StringUtils.hasText(gestno)) {
if (comparePart.contains(removeLeadingZeros(gestno))) {
return lianZhongPatPicDir;
}
}
if (comparePart.contains(removeLeadingZeros(patno))) {
return lianZhongPatPicDir;
}
}
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);
}
}