如何将PDF文件切分成图片进行存储?


如何将PDF文件切分成图片进行存储?

前段时间,老板接到一个需求,说是某个小程序打开PDF文件加载太慢了?开发团队的同学一脸闷逼,大家不都是这样做的?提升服务器的带宽不就可以了么 。
结果运维同学在提升了服务器带宽 , 增加了服务器内存之后,老板到客户面前去装X的时候,还是翻车了 。所以就要求开发同学一定要解决这个问题 。
我们日常使用的PDF,有两种形式
  • 文档形式的PDF:通过Word文档或者PPT等内容导出生成的PDF 。
  • 图片形式的PDF:通过图片生成的PDF
根据这个思路,我们可以将PDF的每一页切分成一个图片,这样按照图片加载内容 , 总比直接加载一个一两百兆的PDF文件要加载的快吧 , 说干就干 。下面我们就来看看如何去实现一个PDF文件的切分 。

创建一个文件上传的接口

在这个接口中主要完成PDF文件的上传工作 。
/*** 通用上传请求(单个)*/@PostMapping("/uploadPdf")@ResponseBodypublic AjaxResult uploadFilePdf(MultipartFile file) throws Exception{try{String prefix = RuoYiConfig.getImageProxyPath();// 上传文件路径String filePath = RuoYiConfig.getUploadPath();// 上传并返回新文件名称String fileName = FileUploadUtils.uploadPdf(filePath, file);String url = prefixfileName;AjaxResult ajax = AjaxResult.success();ajax.put("url", url);ajax.put("fileName", fileName);ajax.put("newFileName", FileUtils.getName(fileName));ajax.put("originalFilename", file.getOriginalFilename());return ajax;}catch (Exception e){return AjaxResult.error(e.getMessage());}}

PDF文件切分操作

首先需要引入两个POM的依赖
org.apache.pdfboxpdfbox2.0.24com.itextpdfitextpdf5.5.13.2
编写一个接收PDF文件并且进行拆分的方法
/*** 将PDF文档拆分成图像列表** @param pdf PDF文件*/private static List getImgList(File pdf) throws IOException {PDDocument pdfDoc = PDDocument.load(pdf);log.info("加载PDF文件成功");List imgList = new ArrayList<>();PDFRenderer pdfRenderer = new PDFRenderer(pdfDoc);int numPages = pdfDoc.getNumberOfPages();log.info("获取到PDF文件页码 {}",numPages);Instant start = Instant.now();for (int i = 0; i < numPages; i) {BufferedImage image = pdfRenderer.renderImageWithDPI(i, 300, ImageType.RGB);imgList.add(image);}Instant end = Instant.now();Duration duration = Duration.between(start, end);log.info("分解PDF Time elapsed: "duration.toMillis()" milliseconds");pdfDoc.close();return imgList;}
将图片切分成一个List列表之后,接下来的操作就是将这个列表转换成对应的图片进行存储 。
/*** PDF分解图片文件** @param pdfpdf文件* @param outDir 输出文件夹*/public static List cutPNG(File pdf, File outDir) throws IOException {log.info("PDF分解图片工作开始");String pdfName = pdf.getName();List fileNameList = new ArrayList<>();List list = getImgList(pdf);log.info(pdf.getName()" 一共发现了 "list.size()" 页");FileUtils.cleanDir(outDir);Instant start = Instant.now();String outDirPath = outDir.getAbsolutePath();String name = outDir.getCanonicalPath();log.info("获取输出文件路径 {}",outDirPath);for (int i = 0; i < list.size(); i) {Map fileMap = new HashMap<>();String format = StringUtils.format("{}/{}/{}.png", DateUtils.datePath(),pdfName.substring(0,pdfName.lastIndexOf(".")).trim() "_pngs",i 1);IMGUtils.saveImageToFile(list.get(i),outDirPathFile.separator(i1)".png");String pathFileName = FileUploadUtils.getPathFileName(RuoYiConfig.getUploadPath(), format);fileMap.put("pageNumber",i 1);fileMap.put("filePath",RuoYiConfig.getImageProxyPath() pathFileName);fileNameList.add(fileMap);}Instant end = Instant.now();Duration duration = Duration.between(start, end);log.info("保存图片 Time elapsed: "duration.toMillis()" milliseconds");log.info("PDF分解图片工作结束 , 一共分解出"list.size()"个图片文件,保存至:"outDir.getAbsolutePath());return fileNameList;}
保存图像到指定路径
/*** 保存图像到指定文件* @param image 图像* @param filePath 文件路径*/ public static void saveImageToFile(BufferedImage image, String filePath) throws IOException {FileUtils.saveDataToFile(filePath,getBytes(image)); }
将数据保存到指定的路径
/** * 将数据保存到指定文件路径 */public static void saveDataToFile(String filePath,byte[] data) throws IOException {File file = new File(filePath);if(!file.exists()){file.createNewFile() ;}FileOutputStream outStream = new FileOutputStream(file);outStream.write(data);outStream.flush();outStream.close();}
【如何将PDF文件切分成图片进行存储?】最终通过这样的操作可以让PDF转换换成一张一张的图片 。然后通过getList的方式去加载这些图片 。就不会出现因为PDF文件过大而导致的加载缓慢的问题 。

相关经验推荐