001package top.cenze.utils.file; 002 003import cn.hutool.core.collection.CollectionUtil; 004import cn.hutool.core.io.FileUtil; 005import cn.hutool.core.util.ObjectUtil; 006import cn.hutool.core.util.StrUtil; 007import lombok.SneakyThrows; 008import lombok.extern.slf4j.Slf4j; 009import org.apache.pdfbox.io.MemoryUsageSetting; 010import org.apache.pdfbox.multipdf.PDFMergerUtility; 011import org.apache.pdfbox.pdmodel.PDDocument; 012import org.apache.pdfbox.rendering.PDFRenderer; 013import org.springframework.web.multipart.MultipartFile; 014 015import javax.imageio.ImageIO; 016import java.awt.image.BufferedImage; 017import java.io.File; 018import java.io.FileInputStream; 019import java.io.IOException; 020import java.io.OutputStream; 021import java.net.HttpURLConnection; 022import java.net.URL; 023import java.util.List; 024 025/** 026 * PDF工具类 027 */ 028@Slf4j 029public class PDFUtil { 030 /** 031 * 获取PDF总页数 032 * @throws IOException 033 */ 034 public static int getPageNum(String src) throws IOException { 035 PDDocument pdDocument = null; 036 int pages = 0; 037 038 try { 039 pdDocument = getPDDocument(src); 040 pages = pdDocument.getNumberOfPages(); 041 } catch (Exception e) { 042 e.printStackTrace(); 043 log.error(e.getMessage(), e); 044 } finally { 045 if (pdDocument != null) { 046 pdDocument.close(); 047 } 048 } 049 050 return pages; 051 } 052 053 /** 054 * PDF转图片 根据页码一页一页转 055 * @throws IOException 056 */ 057 public static BufferedImage toImg(String src, int page) throws IOException { 058 PDDocument pdDocument = null; 059 /* dpi越大转换后越清晰,相对转换速度越慢 */ 060 int dpi = 100; 061 page --; 062 063 try { 064 pdDocument = getPDDocument(src); 065 PDFRenderer renderer = new PDFRenderer(pdDocument); 066 067 int pages = pdDocument.getNumberOfPages(); 068 log.info("PdfToImg pages: {}", pages); 069 070 if (page <= pages && page >= 0) { 071 BufferedImage image = renderer.renderImageWithDPI(page, dpi); 072 073 return image; 074 } 075 } catch (Exception e) { 076 e.printStackTrace(); 077 log.error(e.getMessage(), e); 078 } finally { 079 if (pdDocument != null) { 080 pdDocument.close(); 081 } 082 } 083 084 return null; 085 } 086 087 /** 088 * PDF转图片 根据页码一页一页转,写入输出流 089 * @throws IOException 090 * imgType:转换后的图片类型 jpg,png 091 */ 092 public static void toImgOutputStream(OutputStream os, String src, int page, String imgType) throws IOException { 093 094 BufferedImage bufferedImage = toImg(src, page); 095 096 if (null != bufferedImage) { 097 ImageIO.write(bufferedImage, imgType, os); 098 } 099 } 100 101 private static PDDocument getPDDocument(String src) throws IOException { 102 if (StrUtil.isNotEmpty(src)) { 103 // http文件,需要使用文件下载链接,否则无法正常读取文件内容(比如使用在线浏览链接,读取则会失败) 104 if ("http".equalsIgnoreCase(src.substring(0, 4))) { 105 try{ 106 107 URL url= new URL(src); 108 109 HttpURLConnection connection = (HttpURLConnection) url.openConnection(); 110 111 return PDDocument.load(connection.getInputStream()); 112 }catch(Exception e) { 113 log.error(e.getMessage(), e); 114 } 115 } 116 // 本地文件 117 else { 118 File file = new File(src); 119 FileInputStream inputStream = new FileInputStream(file); 120 121 return PDDocument.load(inputStream); 122 } 123 } 124 125 return null; 126 } 127 128 /** 129 * 多个文件合并为一个 130 * @param lstMultiFile 131 * @return 132 */ 133 @SneakyThrows 134 public static MultipartFile mulFile2One(List<MultipartFile> lstMultiFile) { 135 if (CollectionUtil.isEmpty(lstMultiFile)) { 136 return null; 137 } 138 139 File pdf = CZFileUtil.createPdfFile(); 140 if (ObjectUtil.isNull(pdf) || !FileUtil.exist(pdf)) { 141 return null; 142 } 143 log.info("mulFile2One to new file path: {}", pdf.getPath()); 144 145 PDFMergerUtility mergePdf = new PDFMergerUtility(); 146 for (MultipartFile file : lstMultiFile) { 147 if (ObjectUtil.isNull(file) || "".equals(file) || file.getSize() <= 0) { 148 continue; 149 } 150 log.info("mulFile2One file name: {}", file.getOriginalFilename()); 151 152 mergePdf.addSource(file.getInputStream()); 153 } 154 155 mergePdf.setDestinationFileName(pdf.getPath()); // 设置合并生成pdf文件路径 156 mergePdf.mergeDocuments(MemoryUsageSetting.setupMainMemoryOnly()); // 合并pdf 157 158 pdf = CZFileUtil.loadFile(pdf.getPath()); 159 if (ObjectUtil.isNull(pdf) || !FileUtil.exist(pdf) || pdf.length() <= 0) { 160 return null; 161 } 162 log.info("mulFile2One return file name: {}, size: {}", pdf.getName(), pdf.length()); 163 164 MultipartFile multipartFile = MultipartFileUtil.getMultipartFile(pdf); 165 166 FileUtil.del(pdf); 167 168 return multipartFile; 169 } 170}