PicUtil(文件压缩工具类)

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
/**
* 文件压缩工具类
* @author Eliauk
*/
public class PicUtil {

public static byte[] compressPictureForScale(String srcPath, long desFileSize, double accuracy) throws IOException {
if (StringUtils.isEmpty(srcPath)) {
return null;
}
File srcFile = new File(srcPath);
if (!srcFile.exists()) {
return null;
}

String formatName = FilenameUtils.getExtension(srcPath);
BufferedImage image;
try {
long srcFileSize = srcFile.length();
System.out.println("源图片: " + srcPath + ", 大小: " + srcFileSize / 1024 + "kb");

image = Thumbnails.of(srcPath).scale(1f).asBufferedImage();
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
compressPicCycle(image, desFileSize, accuracy, formatName, byteArrayOutputStream);
image.getGraphics().dispose();

System.out.println("图片压缩完成!");

byte[] byteArray = byteArrayOutputStream.toByteArray();
System.out.println("源图片压缩后为: " + srcPath + ", 大小: " + byteArray.length / 1024 + "kb");
byteArrayOutputStream.close();
return byteArray;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}

private static void compressPicCycle(BufferedImage desImage, long desFileSize, double accuracy, String formatName, ByteArrayOutputStream byteArrayOutputStream) throws IOException, IOException {
byteArrayOutputStream.reset();
ImageIO.write(desImage, formatName, byteArrayOutputStream);
byte[] byteArray = byteArrayOutputStream.toByteArray();
if (byteArray.length / 1024 > desFileSize) {
int srcWidth = desImage.getWidth();
int srcHeight = desImage.getHeight();
int destWidth = new BigDecimal(srcWidth).multiply(new BigDecimal(accuracy)).intValue();
int destHeight = new BigDecimal(srcHeight).multiply(new BigDecimal(accuracy)).intValue();
BufferedImage image = Thumbnails.of(desImage).size(destWidth, destHeight).outputQuality(accuracy).asBufferedImage();
compressPicCycle(image, desFileSize, accuracy, formatName, byteArrayOutputStream);
}
}
}

IBaseEnum(通用枚举接口)

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
/**
* @author Eliauk
* @since 2023/9/28 14:40
*/


public interface IBaseEnum {

Object getValue();
String getLabel();

/**
* 获取与给定值匹配的枚举常量。
*
* @param <E> 继承自Enum并且实现IBaseEnum的泛型
* @param value 要查找的值
* @param clazz 枚举类的Class对象
* @return 与给定值匹配的枚举常量,如果没有找到则返回null
* @throws NullPointerException 如果提供的值为null
*/
static <E extends Enum<E> & IBaseEnum> E getEnumByValue(Object value, Class<E> clazz) {
Objects.requireNonNull(value);
EnumSet<E> allEnums = EnumSet.allOf(clazz);
return allEnums.stream().filter(e -> value.equals(e.getValue())).findFirst().orElse(null);
}

/**
* 通过给定的值获取枚举常量的标签。
*
* @param <E> 继承自Enum并且实现IBaseEnum的泛型
* @param value 要查找的值
* @param clazz 枚举类的Class对象
* @return 与给定值匹配的枚举标签,如果没有找到则返回null
*/
static <E extends Enum<E> & IBaseEnum> String getLabelByValue(Object value, Class<E> clazz) {
E matchEnum = getEnumByValue(value, clazz);
String label = null;
if (Objects.nonNull(matchEnum)) {
label = matchEnum.getLabel();
}
return label;
}

/**
* 通过给定的标签获取匹配的枚举常量。
*
* @param <E> 继承自Enum并且实现IBaseEnum的泛型
* @param label 要查找的标签
* @param clazz 枚举类的Class对象
* @return 与给定标签匹配的枚举常量,如果没有找到则返回null
* @throws NullPointerException 如果提供的标签为null
*/
static <E extends Enum<E> & IBaseEnum> E getEnumByLabel(String label, Class<E> clazz) {
Objects.requireNonNull(label);
EnumSet<E> allEnums = EnumSet.allOf(clazz);
Optional<E> match = allEnums.stream().filter(e -> label.equals(e.getLabel())).findFirst();
return match.orElse(null);
}

}

TextValidator(正则工具类)

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
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
/**
* 通过正则表达判断是否正确的手机号,固定电话,身份证,邮箱等.
* <p>
* 从AndroidUtilCode的RegexUtils移植, 性能优化将正则表达式为预编译, 并修改了TEL的正则表达式.
*
* @author Eliauk
*/
public class TextValidator {

/**
* 正则:手机号(简单), 1字头+10位数字即可.
*/
private static final String REGEX_MOBILE_SIMPLE = "^[1]\\d{10}$";
private static final Pattern PATTERN_REGEX_MOBILE_SIMPLE = Pattern.compile(REGEX_MOBILE_SIMPLE);

/**
* 正则:手机号(精确), 已知3位前缀+8位数字
* <p>
* 移动:134(0-8)、135、136、137、138、139、147、150、151、152、157、158、159、178、182、183、184、187、188
* </p>
* <p>
* 联通:130、131、132、145、155、156、175、176、185、186
* </p>
* <p>
* 电信:133、153、173、177、180、181、189
* </p>
* <p>
* 全球星:1349
* </p>
* <p>
* 虚拟运营商:170
* </p>
*/
private static final String REGEX_MOBILE_EXACT = "^((13[0-9])|(14[5,7])|(15[0-3,5-9])|(17[0,3,5-8])|(18[0-9])|(147))\\d{8}$";
private static final Pattern PATTERN_REGEX_MOBILE_EXACT = Pattern.compile(REGEX_MOBILE_EXACT);

/**
* 正则:固定电话号码,可带区号,然后6至少8位数字
*/
private static final String REGEX_TEL = "^(\\d{3,4}-)?\\d{6,8}$";
private static final Pattern PATTERN_REGEX_TEL = Pattern.compile(REGEX_TEL);

/**
* 正则:身份证号码15位, 数字且关于生日的部分必须正确
*/
private static final String REGEX_ID_CARD15 = "^[1-9]\\d{7}((0\\d)|(1[0-2]))(([0|1|2]\\d)|3[0-1])\\d{3}$";
private static final Pattern PATTERN_REGEX_ID_CARD15 = Pattern.compile(REGEX_ID_CARD15);

/**
* 正则:身份证号码18位, 数字且关于生日的部分必须正确
*/
private static final String REGEX_ID_CARD18 = "^[1-9]\\d{5}[1-9]\\d{3}((0\\d)|(1[0-2]))(([0|1|2]\\d)|3[0-1])\\d{3}([0-9Xx])$";
private static final Pattern PATTERN_REGEX_ID_CARD18 = Pattern.compile(REGEX_ID_CARD18);

/**
* 正则:邮箱, 有效字符(不支持中文), 且中间必须有@,后半部分必须有.
*/
private static final String REGEX_EMAIL = "^\\w+([-+.]\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*$";
private static final Pattern PATTERN_REGEX_EMAIL = Pattern.compile(REGEX_EMAIL);

/**
* 正则:URL, 必须有"://",前面必须是英文,后面不能有空格
*/
private static final String REGEX_URL = "[a-zA-z]+://[^\\s]*";
private static final Pattern PATTERN_REGEX_URL = Pattern.compile(REGEX_URL);

/**
* 正则:yyyy-MM-dd格式的日期校验,已考虑平闰年
*/
private static final String REGEX_DATE = "^(?:(?!0000)[0-9]{4}-(?:(?:0[1-9]|1[0-2])-(?:0[1-9]|1[0-9]|2[0-8])|(?:0[13-9]|1[0-2])-(?:29|30)|(?:0[13578]|1[02])-31)|(?:[0-9]{2}(?:0[48]|[2468][048]|[13579][26])|(?:0[48]|[2468][048]|[13579][26])00)-02-29)$";
private static final Pattern PATTERN_REGEX_DATE = Pattern.compile(REGEX_DATE);

/**
* 正则:IP地址
*/
private static final String REGEX_IP = "((2[0-4]\\d|25[0-5]|[01]?\\d\\d?)\\.){3}(2[0-4]\\d|25[0-5]|[01]?\\d\\d?)";
private static final Pattern PATTERN_REGEX_IP = Pattern.compile(REGEX_IP);

/////////////////

/**
* 验证手机号(简单)
*/
public static boolean isMobileSimple(CharSequence input) {
return isMatch(PATTERN_REGEX_MOBILE_SIMPLE, input);
}

/**
* 验证手机号(精确)
*/
public static boolean isMobileExact(CharSequence input) {
return isMatch(PATTERN_REGEX_MOBILE_EXACT, input);
}

/**
* 验证固定电话号码
*/
public static boolean isTel(CharSequence input) {
return isMatch(PATTERN_REGEX_TEL, input);
}

/**
* 验证15或18位身份证号码
*/
public static boolean isIdCard(CharSequence input) {
return isMatch(PATTERN_REGEX_ID_CARD15, input) || isMatch(PATTERN_REGEX_ID_CARD18, input);
}

/**
* 验证邮箱
*/
public static boolean isEmail(CharSequence input) {
return isMatch(PATTERN_REGEX_EMAIL, input);
}

/**
* 验证URL
*/
public static boolean isUrl(CharSequence input) {
return isMatch(PATTERN_REGEX_URL, input);
}

/**
* 验证yyyy-MM-dd格式的日期校验,已考虑平闰年
*/
public static boolean isDate(CharSequence input) {
return isMatch(PATTERN_REGEX_DATE, input);
}

/**
* 验证IP地址
*/
public static boolean isIp(CharSequence input) {
return isMatch(PATTERN_REGEX_IP, input);
}

public static boolean isMatch(Pattern pattern, CharSequence input) {
return StringUtils.isNotEmpty(input) && pattern.matcher(input).matches();
}
}

DirectoryScanner(文件扫描工具类)

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
/**
* 文件扫描工具类
* @author Eliauk
*/
public class DirectoryScanner {

/**
* 递归地遍历指定的文件夹及其所有子文件夹,查找包含具有合法后缀名的图片文件的文件夹。
* 找到这样的文件夹后,将其添加到给定的fileFolders列表中。
*
* @param folder 要开始遍历的根文件夹。
* @param fileFolders 用于存储包含合法图片的文件夹的列表。
* @param legalSuffix 合法图片文件后缀名的列表。
*/
static void getFileFoldersWithImages(File folder, List<File> fileFolders, List<String> legalSuffix) {
File[] subFiles = folder.listFiles();
if (subFiles != null) {
boolean containsValidImage = false;
for (File subFile : subFiles) {
if (subFile.isFile() && legalSuffix.contains(FileUtil.getSuffix(subFile).toLowerCase())) {
containsValidImage = true;
break;
}
}
if (containsValidImage) {
fileFolders.add(folder);
}
for (File subFolder : subFiles) {
if (subFolder.isDirectory()) {
getFileFoldersWithImages(subFolder, fileFolders, legalSuffix);
}
}
}
}

/**
* 递归遍历给定目录及其子目录,找出包含指定后缀名(通常为PDF)的文件夹。
* 将这些包含有符合后缀名条件的文件的文件夹添加到fileFolders列表中。
*
* @param directoryPath 待遍历的目录路径。
* @param fileFolders 存储包含有特定后缀名文件的文件夹的列表。
* @param legalSuffix 有效的文件后缀名列表。
*/
static void getFoldersWithPDFFiles(String directoryPath, List<File> fileFolders, List<String> legalSuffix) {
File rootFolder = new File(directoryPath);
if (rootFolder.isDirectory()) {
File[] fileList = rootFolder.listFiles();
if (fileList != null) {
for (File file : fileList) {
if (file.isDirectory()) {
// 递归处理子目录
getFoldersWithPDFFiles(file.getAbsolutePath(), fileFolders, legalSuffix);
} else if (file.isFile() && legalSuffix.contains(getFileExtension(file))) {
// 当前文件是PDF文件,将其父目录加入待解析目录列表
File parentFolder = file.getParentFile();
if (!fileFolders.contains(parentFolder)) {
fileFolders.add(parentFolder);
}
}
}
}
}
}
static 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;
}



}

ConvertToPDF(各种类型文件转换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
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
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
public byte[] convertToPdf(List<byte[]> files) throws IOException {
// calculate mime type in advance
Tika tika = new Tika();

List<String> mimeTypes = files.stream().map(fileData -> {
try (TikaInputStream tikaStream = TikaInputStream.get(fileData)) {
return tika.detect(tikaStream);
} catch (IOException e) {
throw new RuntimeException(e);
}
}).collect(Collectors.toList());

if (mimeTypes.stream().noneMatch(mimeType -> mimeType != null && mimeType.toLowerCase().contains("pdf"))) {
ByteArrayOutputStream finalOutputStream = new ByteArrayOutputStream();
PdfWriter finalWriter = new PdfWriter(finalOutputStream);
PdfDocument finalPdf = new PdfDocument(finalWriter);
Document finalDocument = new Document(finalPdf);

for (int i = 0; i < files.size(); i++) {
byte[] fileData = files.get(i);
String mimeType = mimeTypes.get(i);

try (InputStream inputStream = new ByteArrayInputStream(fileData)) {
if (mimeType != null && (mimeType.toLowerCase().contains("png")
|| mimeType.toLowerCase().contains("jpg") || mimeType.toLowerCase().contains("jpeg"))) {
com.itextpdf.io.image.ImageData imageData = ImageDataFactory.create(changeDPI(fileData));
Image image = new Image(imageData);
PageSize pageSize = new PageSize(image.getImageWidth(), image.getImageHeight());
finalDocument.getPdfDocument().addNewPage(pageSize);
// 使用已有的布局器,并将页面边距设置为0
finalDocument.setMargins(0, 0, 0, 0);
// 将图像添加到已有的布局器
finalDocument.add(image);
if (i == files.size() - 1) {
finalDocument.add(new AreaBreak(AreaBreakType.NEXT_PAGE));
finalDocument.close();
return finalOutputStream.toByteArray();
}
} else if (mimeType != null && (mimeType.toLowerCase().contains("tiff") || mimeType.toLowerCase().contains("tif"))) {
try (ImageInputStream imageInputStream = ImageIO.createImageInputStream(inputStream)) {
Iterator<ImageReader> imageReaders = ImageIO.getImageReaders(imageInputStream);
if (imageReaders.hasNext()) {
ImageReader reader = imageReaders.next();
reader.setInput(imageInputStream);
int pageCount = reader.getNumImages(true);
for (int k = 0; k < pageCount; k++) {
BufferedImage page = reader.read(k);
try (ByteArrayOutputStream pageOutputStream = new ByteArrayOutputStream()) {
ImageIO.write(page, "png", pageOutputStream);
ImageData imageData = ImageDataFactory.create(pageOutputStream.toByteArray());
Image image = new Image(imageData);
finalDocument.add(image);
finalDocument.add(new AreaBreak(AreaBreakType.NEXT_PAGE)); // Add a page break after each image
}
}
}
}
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}

finalDocument.close();
finalPdf.close();

return finalOutputStream.toByteArray();
} else {

int batchSize = 50; // 每批处理的文件数量
int totalFiles = files.size();
int batches = (int) Math.ceil((double) totalFiles / batchSize);

ExecutorService executorService = Executors.newFixedThreadPool(Math.min(batches, Runtime.getRuntime().availableProcessors()));

List<CompletableFuture<PDDocument>> futures = new ArrayList<>();

for (int i = 0; i < batches; i++) {
int fromIndex = i * batchSize;
int toIndex = Math.min((i + 1) * batchSize, totalFiles);
List<byte[]> batchFiles = files.subList(fromIndex, toIndex);

CompletableFuture<PDDocument> future = CompletableFuture.supplyAsync(() -> {
PDDocument batchPdf = new PDDocument();
PDFMergerUtility merger = new PDFMergerUtility();
for (byte[] fileData : batchFiles) {
String mimeType = null;
try {
mimeType = URLConnection.guessContentTypeFromStream(new ByteArrayInputStream(fileData));
} catch (IOException e) {
throw new RuntimeException(e);
}
if (isPDF(fileData)) {
try (InputStream inputStream = new ByteArrayInputStream(fileData)) {
PDDocument sourcePdf = PDDocument.load(inputStream);
merger.appendDocument(batchPdf, sourcePdf);
sourcePdf.close();
} catch (IOException e) {
e.printStackTrace();
}
} else if (mimeType != null && (mimeType.toLowerCase().contains("png")
|| mimeType.toLowerCase().contains("jpg") || mimeType.toLowerCase().contains("jpeg"))) {
PDPage page = createPDPageFromImage(batchPdf, fileData);
if (page != null) {
batchPdf.addPage(page);
}
} else if (mimeType != null && (mimeType.toLowerCase().contains("tiff") || mimeType.toLowerCase().contains("tif"))) {
List<byte[]> tiffImages = null;
try {
tiffImages = tiffToImage(fileData);
} catch (IOException e) {
throw new RuntimeException(e);
}
for (byte[] imageFileData : tiffImages) {
PDPage page = createPDPageFromImage(batchPdf, imageFileData);
if (page != null) {
batchPdf.addPage(page);
}
}
}
}
return batchPdf;
}, executorService);

futures.add(future);
}

CompletableFuture<Void> allFutures = CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]));
allFutures.join();

// 构建最终的有序 PDF 文档
// 构建最终的有序 PDF 文档
PDDocument finalPdf = new PDDocument();
PDFMergerUtility merger = new PDFMergerUtility();

for (CompletableFuture<PDDocument> future : futures) {
PDDocument batchPdf = future.join();
merger.appendDocument(finalPdf, batchPdf);
batchPdf.close();
}
PDPage blankPage = new PDPage();
finalPdf.addPage(blankPage);
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
finalPdf.save(outputStream);
finalPdf.close();

executorService.shutdown();

return outputStream.toByteArray();
}

}
/**
* 设置图片的DPI为符合国家文档标准的300DPI便于查看
*
*/
public byte[] changeDPI(byte[] imageData) {
try {
// 从字节数组读取图像
BufferedImage image = ImageIO.read(new ByteArrayInputStream(imageData));

// 获取一个ImageWriter
ImageWriter writer = ImageIO.getImageWritersByFormatName("png").next();

// 准备输出流
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageOutputStream ios = ImageIO.createImageOutputStream(baos);
writer.setOutput(ios);

// 设置DPI为300
IIOMetadata metadata = writer.getDefaultImageMetadata(new ImageTypeSpecifier(image), null);
IIOMetadataNode root = (IIOMetadataNode) metadata.getAsTree("javax_imageio_1.0");
IIOMetadataNode dimension = getChildNode(root, "Dimension");

if (dimension == null) {
dimension = new IIOMetadataNode("Dimension");
root.appendChild(dimension);
}

IIOMetadataNode horiz = getChildNode(dimension, "HorizontalPixelSize");
if (horiz == null) {
horiz = new IIOMetadataNode("HorizontalPixelSize");
dimension.appendChild(horiz);
}

IIOMetadataNode vert = getChildNode(dimension, "VerticalPixelSize");
if (vert == null) {
vert = new IIOMetadataNode("VerticalPixelSize");
dimension.appendChild(vert);
}

horiz.setAttribute("value", Double.toString(25.4 / 300));
vert.setAttribute("value", Double.toString(25.4 / 300));
metadata.setFromTree("javax_imageio_1.0", root);

// 写入图像
writer.write(null, new IIOImage(image, null, metadata), null);

ios.close();
writer.dispose();

return baos.toByteArray();

} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/*
* 将PDF的页拆分为图片
*/
private PDPage createPDPageFromImage(PDDocument pdf, byte[] imageData) {
try (InputStream is = new ByteArrayInputStream(imageData)) {
BufferedImage image = ImageIO.read(is);
if (image == null) {
return null;
}
PDImageXObject imageObject = LosslessFactory.createFromImage(pdf, image);
PDPage page = new PDPage(new PDRectangle(image.getWidth(), image.getHeight()));
try (PDPageContentStream contentStream = new PDPageContentStream(pdf, page)) {
contentStream.drawImage(imageObject, 0, 0, image.getWidth(), image.getHeight());
}
return page;
} catch (IOException e) {
e.printStackTrace();
throw new RuntimeException("Error processing image data", e);
}
}
/*
* 将TIF以及TIFF文件转换成图片
* 适配多页
*/
public List<byte[]> tiffToImage(byte[] tiffData) throws IOException {
List<byte[]> imageFiles = new ArrayList<>();
try (ImageInputStream is = ImageIO.createImageInputStream(new ByteArrayInputStream(tiffData))) {
Iterator<ImageReader> it = ImageIO.getImageReaders(is);
if (it.hasNext()) {
ImageReader reader = it.next();
reader.setInput(is);
for (int i = 0; i < reader.getNumImages(true); i++) {
BufferedImage image = reader.read(i);
try (ByteArrayOutputStream imageStream = new ByteArrayOutputStream()) {
ImageIO.write(image, "png", imageStream);
imageFiles.add(imageStream.toByteArray());
}
}
}
}
return imageFiles;
}
/*
* PDF转图片
*/
public static List<byte[]> pdfToImagePlus(InputStream inputStream) {
List<byte[]> result = new ArrayList<>();
try {
PDDocument document = PDDocument.load(inputStream);
PDFRenderer renderer = new PDFRenderer(document);
for (int i = 0; i < document.getNumberOfPages(); i++) {
BufferedImage bufferedImage = renderer.renderImageWithDPI(i, DEFAULT_DPI);
ByteArrayOutputStream out = new ByteArrayOutputStream();
ImageOutputStream imageOut = ImageIO.createImageOutputStream(out);
ImageIO.write(bufferedImage, DEFAULT_FORMAT, imageOut);
result.add(out.toByteArray());
out.close();
imageOut.close();
inputStream.close();
}
document.close();
} catch (Exception e) {
e.printStackTrace();
}
return result;
}

pom.xml(依赖项)

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
<dependency>
<groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio-tiff</artifactId>
<version>3.6.1</version>
</dependency>
<dependency>
<groupId>org.apache.pdfbox</groupId>
<artifactId>pdfbox</artifactId>
<version>2.0.27</version>
</dependency>
<dependency>
<groupId>org.apache.pdfbox</groupId>
<artifactId>pdfbox-tools</artifactId>
<version>2.0.26</version>
</dependency>
<dependency>
<groupId>org.apache.tika</groupId>
<artifactId>tika-core</artifactId>
<version>2.1.0</version>
</dependency>
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itext7-core</artifactId>
<version>7.1.18</version>
<type>pom</type>
</dependency>
<!--解决PDF转图片的时候jpeg2000问题-->
<dependency>
<groupId>com.github.jai-imageio</groupId>
<artifactId>jai-imageio-jpeg2000</artifactId>
<version>1.3.0</version>
</dependency>
<dependency>
<groupId>org.ofdrw</groupId>
<artifactId>ofdrw</artifactId>
<version>2.0.9</version>
<type>pom</type>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.ofdrw</groupId>
<artifactId>ofdrw-reader</artifactId>
<version>2.0.9</version>
<type>pom</type>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.ofdrw</groupId>
<artifactId>ofdrw-converter</artifactId>
<version>2.0.9</version>
</dependency>