前言
最近在项目中遇到了要在app端预览ppt的问题,客户端直接渲染整个ppt会消耗超长时间并且失败的概率极大。
后来想到可以将ppt按照顺序返回一个图片列表,在参考github上的项目并进行优化后实现。
所需依赖
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>3.9</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-scratchpad</artifactId>
<version>3.9</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.9</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.30</version>
</dependency>
java实现
生成的图片是原ppt图片的一半,缩放2倍到原图大小
生成的图片字体包含虚影,消除虚影
添加日志打印
package com.test.rest.utils;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateTime;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.hslf.model.Slide;
import org.apache.poi.hslf.usermodel.SlideShow;
import org.apache.poi.xslf.usermodel.XMLSlideShow;
import org.apache.poi.xslf.usermodel.XSLFSlide;
import java.awt.*;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.io.*;
import java.util.*;
import java.util.List;
@Slf4j
public class ConvertUtil {
public static List<String> ppt2image(String filePath){
String datePath = DateTime.now().toString(DatePattern.PURE_DATE_PATTERN);
String storagePath = "/Users/mac/Downloads/" + datePath + "/" + System.currentTimeMillis();
log.info("ppt2image filePath :{}, storagePath:{}", filePath, storagePath);
Map<String, Object> map = new HashMap<>();
File file = new File(filePath);
try {
List<String> images = convertPPTtoImage(file, storagePath);
return images;
} catch (Exception e) {
log.error("ppt2image exception, filePath :{}, storagePath:{}, e:{}", filePath, storagePath, e);
return null;
}
}
private static List<String> convertPPTtoImage(File file, String dir) {
long start = System.currentTimeMillis();
File dirFile = new File(dir);
if(!dirFile.exists()){
dirFile.mkdirs();
}
List<String> images = new LinkedList<>();
int isppt = checkFile(file);
if (isppt < 0) {
log.error("this file isn't ppt or pptx.");
return null;
}
try {
FileInputStream is = new FileInputStream(file);
Dimension pgsize = null;
Object[] slide = null;
if(isppt == 0) {
SlideShow ppt = new SlideShow(is);
is.close();
pgsize = ppt.getPageSize();
slide = ppt.getSlides();
}else if(isppt == 1) {
XMLSlideShow xppt = new XMLSlideShow(is);
is.close();
pgsize = xppt.getPageSize();
slide = xppt.getSlides();
}
int scale = 2; // 设置缩放因子
for (int i = 0; i < slide.length; i++) {
log.info("Processing Page {} ... ", i+1);
BufferedImage img = new BufferedImage(pgsize.width*scale,
pgsize.height*scale, BufferedImage.TYPE_INT_RGB);
Graphics2D graphics = img.createGraphics();
graphics.setPaint(Color.white);
//字体阴影修复
graphics.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
graphics.fill(new Rectangle2D.Float(0, 0, pgsize.width*scale,
pgsize.height*scale));
graphics.scale(scale, scale); // 缩放图形
if(isppt==0) {
Slide ss = (Slide)slide[i];
ss.draw(graphics);
}else{
XSLFSlide xss = (XSLFSlide)slide[i];
xss.draw(graphics);
}
String filename = (i + 1) + ".jpg";
File imgFile = new File(dir ,filename);
images.add(imgFile.getAbsolutePath());
FileOutputStream out = new FileOutputStream(imgFile);
javax.imageio.ImageIO.write(img, "jpg", out);
out.close();
}
log.info("completed in {} ms", System.currentTimeMillis() - start);
} catch (Exception e) {
log.error("convertPPTtoImage failed, e:{}", e);
}
return images;
}
private static int checkFile(File file) {
int isppt = -1;
String filename = file.getName();
String suffixname = null;
if (filename.contains(".")) {
suffixname = filename.substring(filename.indexOf("."));
if (suffixname.equals(".ppt")) {
isppt = 0;
}else if (suffixname.equals(".pptx")) {
isppt = 1;
}
}
return isppt;
}
}