123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256 |
- package com.smppw.modaq.infrastructure.util;
- import cn.hutool.core.collection.ListUtil;
- import cn.hutool.core.io.FileUtil;
- import org.apache.pdfbox.Loader;
- import org.apache.pdfbox.io.RandomAccessReadBufferedFile;
- import org.apache.pdfbox.pdmodel.PDDocument;
- import org.apache.pdfbox.rendering.PDFRenderer;
- //import org.docx4j.Docx4J;
- //import org.docx4j.openpackaging.packages.OpcPackage;
- //import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
- import javax.imageio.ImageIO;
- import java.awt.*;
- import java.awt.image.BufferedImage;
- import java.io.*;
- import java.nio.file.Files;
- import java.nio.file.StandardCopyOption;
- import java.util.List;
- public class PdfUtil {
- // public static void validateDocx(String path) throws Exception {
- // File file = new File(path);
- //
- // // 基础检查
- // if (!file.exists()) throw new FileNotFoundException("文件不存在");
- // if (!file.canRead()) throw new IOException("无读取权限");
- // if (file.length() == 0) throw new IOException("文件为空");
- //
- // // 文件头检查
- // try (InputStream is = new FileInputStream(file)) {
- // byte[] header = new byte[4];
- // if (is.read(header) < 4) throw new IOException("文件过小");
- // if (header[0] != 0x50 || header[1] != 0x4B) { // PK 头
- // throw new IOException("不是ZIP格式文件");
- // }
- // }
- //
- // // 尝试作为ZIP打开
- // try (java.util.zip.ZipFile zip = new java.util.zip.ZipFile(file)) {
- // if (zip.getEntry("[Content_Types].xml") == null) {
- // throw new IOException("缺少[Content_Types].xml");
- // }
- // } catch (IOException e) {
- // throw new IOException("无效的ZIP格式: " + e.getMessage());
- // }
- // }
- // public static void convertDocxToPdf(String input, String output) throws Exception {
- // validateDocx(input);
- // try (OutputStream os = new FileOutputStream(output)) {
- // OpcPackage opc = OpcPackage.load(new File(input));
- // if (opc instanceof WordprocessingMLPackage) {
- // Docx4J.toPDF((WordprocessingMLPackage) opc, os);
- // } else {
- // throw new Exception("不是WordprocessingML文档");
- // }
- // }
- // }
- /**
- * 将 PDF 的首页和尾页转换为 PNG 图片
- *
- * @param pdfFilepath 输入的 PDF 文件
- * @param outputDir 输出目录
- * @param dpi 图片分辨率(默认建议 300)
- * @return 生成的图片文件列表
- */
- public static List<String> convertFirstAndLastPagesToPng(String pdfFilepath, File outputDir, int dpi) throws IOException {
- List<String> generatedImages = ListUtil.list(false);
- try (PDDocument document = Loader.loadPDF(new RandomAccessReadBufferedFile(pdfFilepath))) {
- int totalPages = document.getNumberOfPages();
- if (totalPages == 0) {
- throw new IOException("PDF 文件无有效页面");
- }
- // 准备输出目录
- if (!outputDir.exists() && !outputDir.mkdirs()) {
- throw new IOException("无法创建输出目录: " + outputDir);
- }
- String baseName = FileUtil.mainName(pdfFilepath);
- PDFRenderer renderer = new PDFRenderer(document);
- // 始终处理首页(页码从1开始)
- String firstImg = renderPage(renderer, 0, baseName + ".png", outputDir, dpi);
- generatedImages.add(compressAndSave(firstImg));
- // 处理尾页(当总页数 > 1 时)
- if (totalPages > 1) {
- String lastImg = renderPage(renderer, totalPages - 1,
- baseName + "_footer.png",
- outputDir, dpi);
- generatedImages.add(compressAndSave(lastImg));
- }
- }
- return generatedImages;
- }
- /**
- * 渲染单页并保存为图片
- */
- private static String renderPage(PDFRenderer renderer, int pageIndex,
- String fileName, File outputDir, int dpi) throws IOException {
- BufferedImage image = renderer.renderImageWithDPI(pageIndex, dpi);
- File outputFile = new File(outputDir, fileName);
- ImageIO.write(image, "PNG", outputFile);
- return outputFile.getAbsolutePath();
- }
- /**
- * 检查图片分辨率是否超过限制
- *
- * @param image 图片对象
- * @param maxSize 最大允许尺寸(单边像素数)
- * @return 是否超出限制
- */
- private static boolean isResolutionExceeded(BufferedImage image, int maxSize) {
- return image.getWidth() > maxSize || image.getHeight() > maxSize;
- }
- // /**
- // * 压缩图片并转换为Base64
- // *
- // * @param inputFile 输入图片文件
- // * @param maxSize 最大允许尺寸(单边像素数)
- // * @param quality 压缩质量 (0.0-1.0)
- // * @param format 输出格式 ("jpg", "png"等)
- // * @return Base64编码的图片数据
- // */
- // public static String compressAndConvertToBase64(File inputFile, int maxSize, float quality, String format)
- // throws IOException {
- //
- // // 读取原始图片
- // BufferedImage originalImage = ImageIO.read(inputFile);
- //
- // // 检查分辨率是否超出限制
- // if (!isResolutionExceeded(originalImage, maxSize)) {
- // System.out.println("图片尺寸符合要求,无需压缩");
- // }
- //
- // // 计算新尺寸(保持宽高比)
- // int originalWidth = originalImage.getWidth();
- // int originalHeight = originalImage.getHeight();
- // double ratio = (double) maxSize / Math.max(originalWidth, originalHeight);
- // int newWidth = (int) (originalWidth * ratio);
- // int newHeight = (int) (originalHeight * ratio);
- //
- // // 创建缩放后的图片
- // Image scaledImage = originalImage.getScaledInstance(newWidth, newHeight, Image.SCALE_SMOOTH);
- // BufferedImage outputImage = new BufferedImage(newWidth, newHeight, BufferedImage.TYPE_INT_RGB);
- //
- // // 绘制缩放后的图片
- // Graphics2D g2d = outputImage.createGraphics();
- // g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
- // g2d.drawImage(scaledImage, 0, 0, null);
- // g2d.dispose();
- //
- // // 转换为Base64
- // ByteArrayOutputStream baos = new ByteArrayOutputStream();
- // ImageIO.write(outputImage, format, baos);
- // byte[] imageBytes = baos.toByteArray();
- //
- // return Base64.getEncoder().encodeToString(imageBytes);
- // }
- public static String compressAndSave(String inputFile) throws IOException {
- return compressAndSave(FileUtil.file(inputFile));
- }
- public static String compressAndSave(File inputFile) throws IOException {
- int maxSize = 8192;
- String format = FileUtil.extName(inputFile);
- return compressAndSave(inputFile, null, maxSize, format);
- }
- /**
- * 压缩图片并保存到文件
- *
- * @param inputFile 输入文件
- * @param outputFile 输出文件
- * @param maxSize 最大尺寸
- * @param format 输出格式
- */
- public static String compressAndSave(File inputFile, File outputFile, int maxSize, String format)
- throws IOException {
- BufferedImage originalImage = ImageIO.read(inputFile);
- if (!isResolutionExceeded(originalImage, maxSize)) {
- if (outputFile != null) {
- // 直接复制文件
- Files.copy(inputFile.toPath(), outputFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
- return outputFile.getAbsolutePath();
- }
- return inputFile.getAbsolutePath();
- }
- if (outputFile == null) {
- outputFile = inputFile;
- }
- int originalWidth = originalImage.getWidth();
- int originalHeight = originalImage.getHeight();
- double ratio = (double) maxSize / Math.max(originalWidth, originalHeight);
- int newWidth = (int) (originalWidth * ratio);
- int newHeight = (int) (originalHeight * ratio);
- Image scaledImage = originalImage.getScaledInstance(newWidth, newHeight, Image.SCALE_SMOOTH);
- BufferedImage outputImage = new BufferedImage(newWidth, newHeight, BufferedImage.TYPE_INT_RGB);
- Graphics2D g2d = outputImage.createGraphics();
- g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
- g2d.drawImage(scaledImage, 0, 0, null);
- g2d.dispose();
- // 保存到文件
- ImageIO.write(outputImage, format, outputFile);
- return outputFile.getAbsolutePath();
- }
- public static void main(String[] args) {
- try {
- // 示例用法
- File inputFile = new File("D:\\home\\wwwroot\\daq_report_file\\wangzaijun@simuwang.com\\20250605\\image\\泓湖泓福积极配置2期私募证券投资基金-周报-20250530.png");
- int maxSize = 8192; // OpenAI限制
- // 1. 检查图片是否超出限制
- BufferedImage image = ImageIO.read(inputFile);
- if (isResolutionExceeded(image, maxSize)) {
- System.out.println("图片超出尺寸限制,需要压缩");
- System.out.println("原始尺寸: " + image.getWidth() + "x" + image.getHeight());
- // // 2. 压缩并转换为Base64
- // String base64Image = compressAndConvertToBase64(inputFile, maxSize, 0.85f, "png");
- // System.out.println("Base64 数据长度: " + base64Image.length());
- // System.out.println("Base64 前缀: " + base64Image.substring(0, 50) + "...");
- // 3. 压缩并保存到文件
- File outputFile = new File("D:\\home\\wwwroot\\daq_report_file\\wangzaijun@simuwang.com\\20250605\\image\\泓湖泓福积极配置2期私募证券投资基金-周报-20250530.png");
- String output = compressAndSave(inputFile, outputFile, maxSize, "png");
- System.out.println("图片已压缩保存到: " + output);
- // 验证压缩后尺寸
- BufferedImage compressedImage = ImageIO.read(outputFile);
- System.out.println("压缩后尺寸: " + compressedImage.getWidth() + "x" + compressedImage.getHeight());
- } else {
- System.out.println("图片尺寸符合要求");
- }
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- }
|