写这篇文章的目的是让大家都可以学到东西,核心代码中列出了处理思维和调用方法,业务代码已经过滤掉了,希望大家不要做crud程序员!!要思考。。。该博客不懂时可联系下方。
1、流程图如下
2、策略描述
实现方式:
设计模式:父策略调动子策略
业务理念:在不影响原有业务的前提下增加优化
报错机制:当加载logo时报错,直接返回原有文件地址
业务分支:
1、pdf策略:
使用PDDocument处理pdf,主要流程如下
①生成下角PDF(自适应源文件大小)
②拉取源文件到本地
③转换PDF到JPG并合并文件(pdf直接合并会自动分页)
④将转换后的文件重新生成PDF
2、图片策略:
①生成下角PDF(自适应源文件大小)
②拉取源文件到本地
③转换pdf文件成图片并同源文件合并
3、压缩包策略:
根据压缩包的格式走不通的解压 压缩方式
①拉取压缩包到本地
②生成下角PDF
③解压压缩包并将生成的PDF放入
④压缩文件目录
剩余问题(优化性问题):
1、效率问题: 第一次下载文件时,因未处理过需要走策略模式,因处理步骤较多可能会很慢。
2、自适应问题:PDF自适应时会将清晰度降低,目前不走自适应
3、核心代码模块
一、图片格式处理
①生成左小角文件
public void createJpgWithSize(String filePath, float width, float height, Contact contact) {
try (PDDocument document = new PDDocument();
FileOutputStream fio = new FileOutputStream(new File(filePath))) {
// 创建具有指定大小的页面
PDPage page = new PDPage(new PDRectangle(width, height));
try (PDPageContentStream contentStream = new PDPageContentStream(document, page)) {
// 设置字体和颜色
File fontFile = new File("/data/config/easybii/simhei.ttf");
PDType0Font font = PDType0Font.load(document, fontFile);
contentStream.setFont(font, 22);
contentStream.setNonStrokingColor(Color.black);
String phone = " ";
if (StringUtils.isNotBlank(contact.getTelephone())) {
phone += contact.getTelephone();
}
if (StringUtils.isNotBlank(contact.getTelephone1())) {
phone += " " + contact.getTelephone();
}
// 写入文字
contentStream.beginText();
contentStream.newLineAtOffset(20, 15);
contentStream.showText("报价联系人: " + contact.getName() + phone);
contentStream.endText();
}
// 将页面添加到文档中
document.addPage(page);
// 保存文档
document.save(fio);
} catch (IOException e) {
e.printStackTrace();
}
}
②将pdf文件转化为jpg
public void convertPDDocumentToImage(String pdfPath, String outputImagePath) {
try (PDDocument document = PDDocument.load(new File(pdfPath))) {
PDFRenderer renderer = new PDFRenderer(document);
BufferedImage image = renderer.renderImageWithDPI(0, 300); // 0 表示第一页,300 是 DPI
javax.imageio.ImageIO.write(image, "jpg", new File(outputImagePath));
} catch (IOException e) {
e.printStackTrace();
}
}
③压缩尺寸
/**
* 压缩尺寸
*
* @param sourceImagePath
* @param targetImagePath
* @param targetWidth
* @param targetHeight
*/
public void resizeJpg(String sourceImagePath, String targetImagePath, float targetWidth, float targetHeight) {
try {
BufferedImage sourceImage = ImageIO.read(new File(sourceImagePath));
float sourceWidth = sourceImage.getWidth();
float sourceHeight = sourceImage.getHeight();
double scaleX = (double) targetWidth / sourceWidth;
double scaleY = (double) targetHeight / sourceHeight;
double scale = Math.min(scaleX, scaleY);
int newWidth = (int) (sourceWidth * scale);
int newHeight = (int) (sourceHeight * scale);
BufferedImage resizedImage = new BufferedImage(newWidth, newHeight, BufferedImage.TYPE_INT_RGB);
Graphics2D graphics2D = resizedImage.createGraphics();
graphics2D.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
graphics2D.drawImage(sourceImage, 0, 0, newWidth, newHeight, null);
graphics2D.dispose();
ImageIO.write(resizedImage, "jpg", new FileOutputStream(new File(targetImagePath)));
} catch (IOException e) {
e.printStackTrace();
}
}
④合并俩个图片
/**
* 将俩张图片合并为一张图片
*
* @param image1Path
* @param image2Path
* @param mergedImagePath
*/
public String mergeJpgImages(String image1Path, String image2Path, String mergedImagePath) {
try {
ImageInputStream input1 = ImageIO.createImageInputStream(new File(image1Path));
ImageReader reader1 = ImageIO.getImageReaders(input1).next();
reader1.setInput(input1);
BufferedImage image1 = reader1.read(0);
ImageInputStream input2 = ImageIO.createImageInputStream(new File(image2Path));
ImageReader reader2 = ImageIO.getImageReaders(input2).next();
reader2.setInput(input2);
BufferedImage image2 = reader2.read(0);
int width = Math.max(image1.getWidth(), image2.getWidth());
int height = image1.getHeight() + image2.getHeight();
BufferedImage mergedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
// 绘制第一张图片
mergedImage.getGraphics().drawImage(image1, 0, 0, null);
// 绘制第二张图片在第一张图片下方
mergedImage.getGraphics().drawImage(image2, 0, image1.getHeight(), null);
ImageIO.write(mergedImage, "jpg", new File(mergedImagePath));
} catch (IOException e) {
e.printStackTrace();
}
return mergedImagePath;
}
⑤设置水印
public void addWatermark(String imagePath, String outputPath, String watermarkText) {
try (FileOutputStream fio = new FileOutputStream(outputPath)) {
BufferedImage image = ImageIO.read(new File(imagePath));
Graphics2D g2d = image.createGraphics();
// 设置字体
Font font = new Font("Arial", Font.PLAIN, 50);
g2d.setFont(font);
// 设置颜色和透明度
Color color = new Color(12, 12, 12, 45);
g2d.setColor(color);
int imageWidth = image.getWidth();
int imageHeight = image.getHeight();
// 计算每行和每列水印文字的数量
int numRows = imageHeight / 50;
int numCols = imageWidth / 100;
// 区分横版和竖版
if (imageWidth > imageHeight) {
// 横版
// 右上角宽度 10%、高度 10%的位置
int xRightTop = (int) (imageWidth * 0.8);
int yRightTop = (int) (imageHeight * 0.2);
AffineTransform transform = new AffineTransform();
transform.rotate(Math.toRadians(-30), xRightTop, yRightTop); // 应用倾斜变换
g2d.setTransform(transform);
g2d.drawString(watermarkText, xRightTop, yRightTop);
// 左下角宽度 10%、高度 90%的位置
int xLeftBottom = (int) (imageWidth * 0.1);
int yLeftBottom = (int) (imageHeight * 0.9);
AffineTransform transform2 = new AffineTransform();
transform2.rotate(Math.toRadians(-30), xLeftBottom, yLeftBottom); // 应用倾斜变换
g2d.setTransform(transform2);
g2d.drawString(watermarkText, xLeftBottom, yLeftBottom);
// 中间
int xMiddle = imageWidth / 2 - watermarkText.length() * 5;
int yMiddle = imageHeight / 2;
AffineTransform transform3 = new AffineTransform();
transform3.rotate(Math.toRadians(-30), xMiddle, yMiddle); // 应用倾斜变换
g2d.setTransform(transform3);
g2d.drawString(watermarkText, xMiddle, yMiddle);
} else {
// 竖版
// 右上角宽度 10%、高度 10%的位置
int xRightTop = (int) (imageWidth * 0.80);
int yRightTop = (int) (imageHeight * 0.1);
AffineTransform transform= new AffineTransform();
transform.rotate(Math.toRadians(-30), xRightTop, yRightTop); // 应用倾斜变换
g2d.setTransform(transform);
g2d.drawString(watermarkText, xRightTop, yRightTop);
// 左下角宽度 90%、高度 90%的位置
int xLeftBottom = (int) (imageWidth * 0.1);
int yLeftBottom = (int) (imageHeight * 0.9);
AffineTransform transform2 = new AffineTransform();
transform2.rotate(Math.toRadians(-30), xLeftBottom, yLeftBottom); // 应用倾斜变换
g2d.setTransform(transform2);
g2d.drawString(watermarkText, xLeftBottom, yLeftBottom);
// 中间
int xMiddle = imageWidth / 2 - watermarkText.length() * 5;
int yMiddle = imageHeight / 2;
AffineTransform transform3 = new AffineTransform();
transform3.rotate(Math.toRadians(-30), xMiddle, yMiddle); // 应用倾斜变换
g2d.setTransform(transform3);
g2d.drawString(watermarkText, xMiddle, yMiddle);
}
g2d.dispose();
// 输出图片
ImageIO.write(image, "jpg", fio);
} catch (IOException e) {
e.printStackTrace();
}
}
二、PDF格式
①生成pdf文件同上
②PDF转图片同上
③转化原有PDF成图片并合并
/**
* 将pdf文件转化成jpg
*
* @param pdf1Path
* @param pdf2Path
*/
public List<String> mergePDFImages(String pdf1Path, String jpgIndex,PDRectangle mediaBox) {
try {
checkAndCreateFolder("oldJpg");
checkAndCreateFolder("newJpg");
List<String> oldJpg = convertPDFToJPG(pdf1Path, "oldJpg");
String path = "mergedImage" + System.currentTimeMillis();
List<String> jpgLists = new ArrayList<>();
int i = 0;
for (String jpgNew : oldJpg) {
mergeJpgImages(jpgNew, jpgIndex, path + i + ".jpg");
//设置水印
this.addWatermark(path + i + ".jpg", path + i + "2.jpg", "easybii");
jpgLists.add(path + i + "2.jpg");
i++;
}
fileWaterCommon.deleteSpecifiedFileInFolder("oldJpg", oldJpg);
return jpgLists;
} catch (Exception e) {
e.printStackTrace();
}
return new ArrayList<>();
}
public void checkAndCreateFolder(String folderPath) {
File folder = new File(folderPath);
if (!folder.exists()) {
if (folder.mkdirs()) {
log.info("文件夹创建成功!");
} else {
log.info("文件夹创建失败!");
}
} else {
log.info("文件夹已存在!");
}
}
/**
* 将 PDF 文件的每一页转换为 JPG 图片
*
* @param pdfFilePath PDF 文件的路径
* @param dstImgFolder 图片保存的文件夹路径
* @return 转换后的图片文件路径列表
*/
public List<String> convertPDFToJPG(String pdfFilePath, String dstImgFolder) {
List<String> imagePaths = new ArrayList<>();
try (PDDocument document = PDDocument.load(new File(pdfFilePath))) {
PDFRenderer renderer = new PDFRenderer(document);
int pageCount = document.getNumberOfPages();
for (int i = 0; i < pageCount; i++) {
String imagePath = dstImgFolder + File.separator + System.currentTimeMillis() + (i + 1) + ".jpg";
BufferedImage image = renderer.renderImageWithDPI(i, 300);
ImageIO.write(image, "jpg", new FileOutputStream(imagePath));
imagePaths.add(imagePath);
}
} catch (IOException e) {
e.printStackTrace();
}
return imagePaths;
}
/**
* 将俩张图片合并为一张图片
*
* @param image1Path
* @param image2Path
* @param mergedImagePath
*/
public String mergeJpgImages(String image1Path, String image2Path, String mergedImagePath) {
try {
ImageInputStream input1 = ImageIO.createImageInputStream(new File(image1Path));
ImageReader reader1 = ImageIO.getImageReaders(input1).next();
reader1.setInput(input1);
BufferedImage image1 = reader1.read(0);
ImageInputStream input2 = ImageIO.createImageInputStream(new File(image2Path));
ImageReader reader2 = ImageIO.getImageReaders(input2).next();
reader2.setInput(input2);
BufferedImage image2 = reader2.read(0);
int width = Math.max(image1.getWidth(), image2.getWidth());
int height = image1.getHeight() + image2.getHeight();
BufferedImage mergedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
// 绘制第一张图片
mergedImage.getGraphics().drawImage(image1, 0, 0, null);
// 绘制第二张图片在第一张图片下方
mergedImage.getGraphics().drawImage(image2, 0, image1.getHeight(), null);
ImageIO.write(mergedImage, "jpg", new File(mergedImagePath));
} catch (IOException e) {
e.printStackTrace();
}
return mergedImagePath;
}
public void addWatermark(String imagePath, String outputPath, String watermarkText) {
try (FileOutputStream fio = new FileOutputStream(outputPath)) {
BufferedImage image = ImageIO.read(new File(imagePath));
Graphics2D g2d = image.createGraphics();
// 设置字体
Font font = new Font("Arial", Font.PLAIN, 50);
g2d.setFont(font);
// 设置颜色和透明度
Color color = new Color(12, 12, 12, 45);
g2d.setColor(color);
int imageWidth = image.getWidth();
int imageHeight = image.getHeight();
// 区分横版和竖版
if (imageWidth > imageHeight) {
// 横版
// 右上角宽度 10%、高度 10%的位置
int xRightTop = (int) (imageWidth * 0.8);
int yRightTop = (int) (imageHeight * 0.2);
AffineTransform transform = new AffineTransform();
transform.rotate(Math.toRadians(-30), xRightTop, yRightTop); // 应用倾斜变换
g2d.setTransform(transform);
g2d.drawString(watermarkText, xRightTop, yRightTop);
// 左下角宽度 10%、高度 90%的位置
int xLeftBottom = (int) (imageWidth * 0.1);
int yLeftBottom = (int) (imageHeight * 0.9);
AffineTransform transform2 = new AffineTransform();
transform2.rotate(Math.toRadians(-30), xLeftBottom, yLeftBottom); // 应用倾斜变换
g2d.setTransform(transform2);
g2d.drawString(watermarkText, xLeftBottom, yLeftBottom);
// 中间
int xMiddle = imageWidth / 2 - watermarkText.length() * 5;
int yMiddle = imageHeight / 2;
AffineTransform transform3 = new AffineTransform();
transform3.rotate(Math.toRadians(-30), xMiddle, yMiddle); // 应用倾斜变换
g2d.setTransform(transform3);
g2d.drawString(watermarkText, xMiddle, yMiddle);
} else {
// 竖版
// 右上角宽度 10%、高度 10%的位置
int xRightTop = (int) (imageWidth * 0.80);
int yRightTop = (int) (imageHeight * 0.1);
AffineTransform transform= new AffineTransform();
transform.rotate(Math.toRadians(-30), xRightTop, yRightTop); // 应用倾斜变换
g2d.setTransform(transform);
g2d.drawString(watermarkText, xRightTop, yRightTop);
// 左下角宽度 90%、高度 90%的位置
int xLeftBottom = (int) (imageWidth * 0.1);
int yLeftBottom = (int) (imageHeight * 0.9);
AffineTransform transform2 = new AffineTransform();
transform2.rotate(Math.toRadians(-30), xLeftBottom, yLeftBottom); // 应用倾斜变换
g2d.setTransform(transform2);
g2d.drawString(watermarkText, xLeftBottom, yLeftBottom);
// 中间
int xMiddle = imageWidth / 2 - watermarkText.length() * 5;
int yMiddle = imageHeight / 2;
AffineTransform transform3 = new AffineTransform();
transform3.rotate(Math.toRadians(-30), xMiddle, yMiddle); // 应用倾斜变换
g2d.setTransform(transform3);
g2d.drawString(watermarkText, xMiddle, yMiddle);
}
//
// // 计算每行和每列水印文字的数量
// int numRows = imageHeight / 50;
// int numCols = imageWidth / 100;
//
// for (int i = 0; i < numRows; i++) {
// for (int j = 0; j < numCols; j++) {
// // 设置文字颜色和透明度
// // 计算文字位置
// int x = j * 500;
// int y = i * 400;
// AffineTransform transform = new AffineTransform();
// transform.rotate(Math.toRadians(-30), x, y); // 应用倾斜变换
// g2d.setTransform(transform);
// // 绘制文字水印
// g2d.drawString(watermarkText, x, y);
// }
// }
g2d.dispose();
// 输出图片
ImageIO.write(image, "jpg", fio);
} catch (IOException e) {
e.printStackTrace();
}
}
④将处理好的jpg生成PDF
public void mergeJpgToPdf(List<String> jpgPaths, String pdfPath) {
try (PDDocument document = new PDDocument()) {
for (String jpgPath : jpgPaths) {
try {
BufferedImage image = fileToBufferedImage(new File(jpgPath));
PDPage page = new PDPage(new org.apache.pdfbox.pdmodel.common.PDRectangle(image.getWidth(), image.getHeight()));
document.addPage(page);
PDPageContentStream contentStream = new PDPageContentStream(document, page);
contentStream.drawImage(LosslessFactory.createFromImage(document, image), 0, 0);
contentStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
document.save(new FileOutputStream(new File(pdfPath)));
for (String jpgPath : jpgPaths) {
deleteFile(jpgPath);
}
} catch (IOException e) {
e.printStackTrace();
}
}
三、压缩包格式
①处理zip格式
/**
* zip格式压缩包处理
*
* @param sourceZipPath
* @param resultPdf
* @param newFilePath
* @param destDirPath
* @param downPdf
* @throws IOException
* @throws URISyntaxException
*/
public void unzipAndRezip(String sourceZipPath, String resultPdf, String newFilePath, String destDirPath, String downPdf) throws IOException, URISyntaxException {
//下载安装包到本地
URL urlPath = new URL(sourceZipPath);
HttpURLConnection connection = (HttpURLConnection) urlPath.openConnection();
InputStream inputStream = connection.getInputStream();
OutputStream outputStream = new FileOutputStream(downPdf);
byte[] buffer = new byte[1024];
int length;
while ((length = inputStream.read(buffer)) > 0) {
outputStream.write(buffer, 0, length);
}
// 关闭InputStream
inputStream.close();
// 关闭OutputStream
outputStream.close();
File destDir = new File(destDirPath);
if (!destDir.exists()) {
destDir.mkdir();
}
this.unzip(downPdf, destDirPath);
// this.addNewFileToDirectory(destDirPath, newFilePath);
this.zipDirectory(destDirPath, resultPdf);
// 清理临时文件夹
deleteDirectory(destDir);
}
/**
* 解压压缩包
*
* @param zipFilePath
* @param destDirectory
* @throws IOException
*/
public void unzip(String zipFilePath, String destDirectory) throws IOException {
ZipInputStream in = new ZipInputStream(new FileInputStream(zipFilePath), Charset.forName("GBK"));
ZipEntry z;
while ((z = in.getNextEntry()) != null) {
if (z.isDirectory()) {
String name = z.getName();
name = name.substring(0, name.length() - 1);
File f = new File(destDirectory + File.separator + name);
if (!f.getParentFile().exists()) {
f.getParentFile().mkdirs();
}
if (!f.exists()) {
f.mkdir();
}
System.out.println("mkdir " + destDirectory + File.separator
+ name);
} else {
File f = new File(destDirectory + File.separator
+ z.getName());
if (!f.getParentFile().exists()) {
f.getParentFile().mkdirs();
}
if (!f.exists()) {
f.createNewFile();
}
FileOutputStream out = new FileOutputStream(f);
//此处注释部分第一次压缩后文件打不开,后来又可以
// int b;
// while ((b = in.read()) != -1) {
// out.write(b);
// }
//下面部分代码替换了上面注释部分的代码压缩正常
byte[] bytes = new byte[1024];
int b = -1;
while ((b = in.read(bytes)) != -1) {
out.write(bytes, 0, b);
}
out.close();
}
}
in.close();
}
/**
* 生成压缩包
*
* @param sourceDirPath
* @param zipFilePath
* @throws IOException
*/
public void zipDirectory(String sourceDirPath, String zipFilePath) throws IOException {
try (ZipOutputStream zipOut = new ZipOutputStream(new FileOutputStream(zipFilePath))) {
Path sourceDir = Paths.get(sourceDirPath);
Files.walk(sourceDir)
.filter(path -> !Files.isDirectory(path))
.forEach(path -> {
ZipEntry zipEntry = new ZipEntry(sourceDir.relativize(path).toString());
try {
zipOut.putNextEntry(zipEntry);
Files.copy(path, zipOut);
zipOut.closeEntry();
} catch (IOException e) {
e.printStackTrace();
}
});
}
}
②下载rar
/**
* 解压rar
*
* @param url rar
* @param extractPath 解压路径
*/
public void unCompress(String url, String extractPath, String downPdf) throws IOException, URISyntaxException {
URL urlPath = new URL(url);
HttpURLConnection connection = (HttpURLConnection) urlPath.openConnection();
InputStream inputStream = connection.getInputStream();
OutputStream outputStream = new FileOutputStream(downPdf);
byte[] buffer = new byte[1024];
int length;
while ((length = inputStream.read(buffer)) > 0) {
outputStream.write(buffer, 0, length);
}
// 关闭InputStream
inputStream.close();
// 关闭OutputStream
outputStream.close();
try {
RandomAccessFile randomAccessFile = new RandomAccessFile(downPdf, "r");
IInArchive archive = SevenZip.openInArchive(null, new RandomAccessFileInStream(randomAccessFile));
// 解压⽂件路径
File extractDir = new File(extractPath);
if (!extractDir.isDirectory()) {
extractDir.mkdir();
}
int[] in = new int[archive.getNumberOfItems()];
for (int i = 0; i < in.length; i++) {
in[i] = i;
}
archive.extract(in, false, new ExtractCallback(archive, extractDir.getAbsolutePath()));
archive.close();
randomAccessFile.close();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 生成压缩包
*
* @param sourceDirPath
* @param zipFilePath
* @throws IOException
*/
public void zipDirectory(String sourceDirPath, String zipFilePath) throws IOException {
try (ZipOutputStream zipOut = new ZipOutputStream(new FileOutputStream(zipFilePath))) {
Path sourceDir = Paths.get(sourceDirPath);
Files.walk(sourceDir)
.filter(path -> !Files.isDirectory(path))
.forEach(path -> {
ZipEntry zipEntry = new ZipEntry(sourceDir.relativize(path).toString());
try {
zipOut.putNextEntry(zipEntry);
Files.copy(path, zipOut);
zipOut.closeEntry();
} catch (IOException e) {
e.printStackTrace();
}
});
}
}