1、策略接口上下文

1
2
3
4
5
6
7
8
9
10
11
@Service
public class PathUploadStrategyContext {

@Resource
private Map<String, PathUploadStrategy> pathUploadStrategyMap;

public void getFileInferStrategy(PathUpLoadMessage message, String strategy) throws IOException {
pathUploadStrategyMap.get(IBaseEnum.getLabelByValue(strategy, PathUploadEnum.class)).upload(message,strategy);
}

}

2、策略抽象实现类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
/**
* 服务器路径上传文件
*
* @author Eliauk
* @since 2023/9/28 15:16
*/
@Service
public abstract class AbstractPathUploadStrategyImpl implements PathUploadStrategy {




private final Logger LOG = LoggerFactory.getLogger(AbstractPathUploadStrategyImpl.class);

@Override
public void upload(PathUpLoadMessage message, String strategy) throws IOException {
LOG.info("开始执行{}服务器路径上传策略", strategy);

if (exist(message)){

LOG.info("档号为{}的档案已经存在,跳过上传",message.getFileName());
return;
}

uploadByPath(message, strategy);

}

/**
* 服务器路径上传抽象方法
* @param message 队列消息
* @param strategy 路径上传策略
* @since 2023/9/28 15:16
*/
abstract void uploadByPath(PathUpLoadMessage message, String strategy) throws IOException;

/**
* 判断当前任务是否已经上传抽象方法
* @param message 队列消息
* @return
* true:已经上传
* false:未上传
* @since 2023/9/28 15:16
*/
abstract boolean exist(PathUpLoadMessage message);

protected List<File> getAllPDFFiles(File rootFolder, List<String> legalSuffix) {
List<File> pdfFiles = new ArrayList<>();
if (rootFolder.isDirectory()) {
File[] fileList = rootFolder.listFiles();
if (fileList != null) {
for (File file : fileList) {
if (file.isDirectory()) {
pdfFiles.addAll(getAllPDFFiles(file, legalSuffix));
} else if (file.isFile() && legalSuffix.contains(getFileExtension(file)) && !file.getName().startsWith("._")) {
pdfFiles.add(file);
}
}
}
}
return pdfFiles;
}

/**
* 获取文件的后缀名
*/
private static String getFileExtension(File file) {
String fileName = file.getName();
int dotIndex = fileName.lastIndexOf(".");
if (dotIndex > 0 && dotIndex < fileName.length() - 1) {
return fileName.substring(dotIndex + 1).toLowerCase();
}
return "";
}
}

3、策略枚举类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
/**
* 服务器路径上传策略枚举
*
* @author Eliauk
* @since 2023/9/28 14:32
*/
@Getter
@AllArgsConstructor
public enum PathUploadEnum implements IBaseEnum{

VOLUME("案卷合并", "volumePathUploadStrategy"),

PDF("PDF文件", "pdfPathUploadStrategy"),

IMAGE_TO_PDF("合并图片文件","mergePicturePathUploadStrategy"),

OFD("OFD文件", "ofdPathUploadStrategy");
private final String value;
private final String label;

@Override
public Object getValue() {
return this.value;
}

@Override
public String getLabel() {
return this.label;
}
}

4、实现类

1、 OdfPathUploadStrategyImpl

OFD转PDF工具源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
/**
* OFD文件服务器路径上传
*
* @author Eliauk
* @since 2023/10/10 9:58
*/
@Service("ofdPathUploadStrategy")
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class OdfPathUploadStrategyImpl extends AbstractPathUploadStrategyImpl{

private static Logger LOG = LoggerFactory.getLogger(OdfPathUploadStrategyImpl.class);
private final AppraisalFileRepository appraisalFileRepository;

private final AppraisalFileService appraisalFileService;

private final IOssEndPoint ossEndPoint;


@Override
void uploadByPath(PathUpLoadMessage message, String strategy) throws IOException {

// 接收所有包含pdf的文件夹
final File file = new File(message.getFile());
final String folderName = file.getName();
// 拿到任务ID
final Long taskId = Convert.toLong(message.getTaskId());
// 拿到租户ID
final String tenantId = message.getTenantId();
// 是否覆盖
final Boolean overWrite = Convert.toBool(message.getOverWrite());
LOG.info("当前进行服务器路径上传OFD的文件夹是{}", folderName);
final List<File> pdfFiles = getAllPDFFiles(file, List.of("ofd"));
long timeStart = DateUtil.current();
long countStart = DateUtil.current();
LOG.info("开始解析文件夹{},包含{}个OFD文件", folderName, pdfFiles.size());

for (int fileIndex = 0; fileIndex < pdfFiles.size(); fileIndex++) {
File ofdFile = pdfFiles.get(fileIndex);
String fileName = ofdFile.getName();
// 判断是否覆盖,如果覆盖就删除原文件,否则跳过
List<AppraisalFile> existingFiles = appraisalFileRepository.findByTaskIdAndFileName(taskId, fileName);
if (!existingFiles.isEmpty()) {
if (overWrite) {
List<Long> existingIds = existingFiles.stream().map(AppraisalFile::getId).collect(Collectors.toList());
appraisalFileService.deleteExistingFiles(existingIds);
} else {
LOG.info("已存在的文件将被跳过: {}", fileName);
continue;
}
}
Attach ofdAttach = null;
try {
// 使用第一个 FileInputStream
try (FileInputStream fileInputStream1 = new FileInputStream(ofdFile)) {
ofdAttach = ossEndPoint.putAttachWithTenant(
new InMemoryMultipartFile(fileName, fileInputStream1),
tenantId
).getData();
}

// 使用第二个 FileInputStream
try (FileInputStream fileInputStream2 = new FileInputStream(ofdFile)) {
ByteArrayOutputStream stream = new ByteArrayOutputStream();
ConvertHelper.toPdf(fileInputStream2, stream);
Attach pdfAttach = ossEndPoint.putAttach(new InMemoryMultipartFile(IdUtil.randomUUID() + ".pdf", stream.toByteArray())
).getData();

AppraisalFile appraisalFile = appraisalFileService.createAppraisalFile(taskId, fileName, pdfAttach);
appraisalFile.setOfdAttach(ofdAttach.getId());
appraisalFile.setFileType(InferFileType.OFD);
appraisalFileRepository.save(appraisalFile);

LOG.info("上传OFD成功所在文件夹名称{} - 当前进度: {}/{},文件名: {},共已耗时: {}s",file.getName(),
fileIndex+1, pdfFiles.size(), fileName, (DateUtil.current() - timeStart) / 1000.0);
}
} catch (Exception e) {
LOG.error("上传文件发生异常: {}", e.getMessage());
}

}
LOG.info("上传OFD成功 - 总文件数: {},耗时: {}s", pdfFiles.size(), (DateUtil.current() - countStart) / 1000.0);

}

@Override
boolean exist(PathUpLoadMessage message) {
return Boolean.FALSE;
}
}

2、VolumePathUploadStrategyImpl

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
/**
* 案卷合并服务器路径上传策略
*
* @author Eliauk
* @since 2023/9/28 16:13
*/
@Service("volumePathUploadStrategy")
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class VolumePathUploadStrategyImpl extends AbstractPathUploadStrategyImpl {

private static Logger LOG = LoggerFactory.getLogger(VolumePathUploadStrategyImpl.class);
private final AppraisalFileRepository appraisalFileRepository;

private final AppraisalFileService appraisalFileService;

private final IOssEndPoint ossEndPoint;

@Override
void uploadByPath(PathUpLoadMessage message, String strategy) throws IOException {


final File uploadFileFolder = new File(message.getFile());
final Long taskId = Convert.toLong(message.getTaskId());
final String tenantId = message.getTenantId();
final Boolean overWrite = Convert.toBool(message.getOverWrite());

File[] imageFiles = uploadFileFolder.listFiles();

// 创建一个Map来存储文件名前缀和相应的文件列表
Map<String, List<File>> groupedFiles = new HashMap<>();
for (File imageFile : imageFiles) {
String name = imageFile.getName();
String prefix = name.substring(0, name.lastIndexOf('-')); // 假设前缀是直到最后一个'-'符号
groupedFiles.computeIfAbsent(prefix, k -> new ArrayList<>()).add(imageFile);
}

LOG.info("开始处理文件夹名称为{}的文件夹,里边最终会合并成{}个文件",uploadFileFolder.getName(),groupedFiles.size());

int pdfNum = 0;
for (Map.Entry<String, List<File>> entry : groupedFiles.entrySet()) {
String prefix = entry.getKey();
List<File> filesInGroup = entry.getValue();

String folderName = prefix; // 你可以根据需要修改
String fileName = folderName + ".pdf";
//pathUpLoadProducer.syncSendPathUpload(tenantId,Convert.toStr(taskId),fileName,Convert.toStr(uploadFileFolder),Convert.toStr(overWrite),PathUploadType.PDF);
// 判断是否覆盖已存在的文件
List<AppraisalFile> existingFiles = appraisalFileRepository.findByTaskIdAndFileName(taskId, fileName);
if (existingFiles.size() > 0) {
if (overWrite) {
List<Long> existingFileIds = existingFiles.stream().map(AppraisalFile::getId).collect(Collectors.toList());
appraisalFileService.deleteExistingFiles(existingFileIds);
} else {
LOG.info("跳过已存在的文件");
pdfNum++;
continue;
}
}

List<byte[]> images = filesInGroup.stream()
.filter(File::isFile)
.map(imageFile -> {
try (InputStream fileInputStream = new FileInputStream(imageFile)) {
return IOUtils.toByteArray(fileInputStream);
} catch (IOException e) {
e.printStackTrace();
return null;
}
})
.filter(Objects::nonNull)
.collect(Collectors.toList());

if (images.isEmpty()) {
pdfNum++;
LOG.info("跳过空文件夹");
continue;
}

final byte[] bytes = appraisalFileService.convertToPdf(images);

byte[] modifiedPdfData= null;
try (PDDocument document = PDDocument.load(bytes)) {
int lastPageNumber = document.getNumberOfPages();

// 删除最后一页
document.removePage(lastPageNumber - 1);

// 保存修改后的PDF
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
document.save(outputStream);
modifiedPdfData = outputStream.toByteArray();


} catch (IOException e) {
// 处理PDF操作异常
e.printStackTrace();
}
Attach pdfAttach = ossEndPoint.putAttachWithTenant(
new InMemoryMultipartFile(fileName, new ByteArrayInputStream(modifiedPdfData)),
tenantId
).getData();

AppraisalFile appraisalFile = appraisalFileService.createAppraisalFile(taskId, fileName, pdfAttach);
appraisalFileRepository.save(appraisalFile);

pdfNum++;
LOG.info("合并处理文件夹名称为{}的PDF成功,当前进度:{}/{},当前文件名:{},共{}页",
folderName, pdfNum, groupedFiles.size(), folderName, images.size());
}

}

@Override
boolean exist(PathUpLoadMessage message) {
return Boolean.FALSE;

}


}

3、MergePicturePathUploadStrategyImpl

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
/**
* 合并图片文件服务器路径上传策略
*
* @author Eliauk
* @since 2023/10/7 16:32
*/
@Service("mergePicturePathUploadStrategy")
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class MergePicturePathUploadStrategyImpl extends AbstractPathUploadStrategyImpl {

private static Logger LOG = LoggerFactory.getLogger(MergePicturePathUploadStrategyImpl.class);
private final AppraisalFileRepository appraisalFileRepository;

private final AppraisalFileService appraisalFileService;

private final IOssEndPoint ossEndPoint;

@Override
void uploadByPath(PathUpLoadMessage message, String strategy) throws IOException {

// 接收所有包含pdf的文件夹
final File file = new File(message.getFile());
final String folderName = file.getName();
// 拿到任务ID
final Long taskId = Convert.toLong(message.getTaskId());
// 拿到租户ID
final String tenantId = message.getTenantId();
// 是否覆盖
final Boolean overWrite = Convert.toBool(message.getOverWrite());
LOG.info("当前进行服务器路径上传进行合并图片文件的文件夹是{}", folderName);

final File[] imageFiles = file.listFiles();
if (ObjectUtil.isNotEmpty(imageFiles)) {
Arrays.sort(imageFiles, Comparator.comparing(File::getName));
}

String fileName = folderName + ".pdf";

// 判断是否覆盖已存在的文件
List<AppraisalFile> existingFiles = appraisalFileRepository.findByTaskIdAndFileName(taskId, fileName);
if (!existingFiles.isEmpty()) {
if (overWrite) {
List<Long> existingFileIds = existingFiles.stream().map(AppraisalFile::getId).collect(Collectors.toList());
appraisalFileService.deleteExistingFiles(existingFileIds);
} else {
LOG.info("跳过已存在的文件");
return;
}
}


if (ObjectUtil.isNotEmpty(imageFiles)) {
Arrays.sort(imageFiles, Comparator.comparing(File::getName));
}

List<byte[]> images = Arrays.stream(imageFiles)
.filter(File::isFile)
.map(imageFile -> {
try (InputStream fileInputStream = new FileInputStream(imageFile)) {
return IOUtils.toByteArray(fileInputStream);
} catch (IOException e) {
e.printStackTrace();
return null;
}
})
.filter(Objects::nonNull)
.collect(Collectors.toList());

if (images.isEmpty()) {

LOG.info("跳过空文件夹");
return;
}

final byte[] bytes = appraisalFileService.convertToPdf(images);

byte[] modifiedPdfData= null;
try (PDDocument document = PDDocument.load(bytes)) {
int lastPageNumber = document.getNumberOfPages();

// 删除最后一页
document.removePage(lastPageNumber - 1);

// 保存修改后的PDF
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
document.save(outputStream);
modifiedPdfData = outputStream.toByteArray();

} catch (IOException e) {
// 处理PDF操作异常
e.printStackTrace();
}
Attach pdfAttach = ossEndPoint.putAttachWithTenant(
new InMemoryMultipartFile(fileName, new ByteArrayInputStream(modifiedPdfData)),
tenantId
).getData();

AppraisalFile appraisalFile = appraisalFileService.createAppraisalFile(taskId, fileName, pdfAttach);
appraisalFileRepository.save(appraisalFile);

LOG.info("当前文件夹名称为{},当前文件名:{},共{}页", folderName ,fileName, images.size());


}

@Override
boolean exist(PathUpLoadMessage message) {
return Boolean.FALSE;
}
}