最近工作需要,要生成office文档的缩略图,调研下来有几个还不错的组件:
- aspose 这个有收费版和免费版,免费版转换篇幅有限制且生成和转化有水印
- spire 这个是本篇博文使用的组件,同样有收费版和免费版,免费版转换有篇幅限制但是没有水印
- libreoffice 这个需要依赖于外部应用,需要把服务部署在所在服务器使用
接下来介绍一下spire的生成office文档和视频文件(使用ffmpeg)缩略图的方法
1. maven依赖:
<repositories>
<repository>
<id>com.e-iceblue</id>
<url>https://repo.e-iceblue.cn/repository/maven-public/</url>
</repository>
</repositories>
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>javacv</artifactId>
<version>1.4.3</version>
</dependency>
<dependency>
<groupId>org.bytedeco.javacpp-presets</groupId>
<artifactId>ffmpeg-platform</artifactId>
<version>4.0.2-1.4.3</version>
</dependency>
<dependency>
<groupId>e-iceblue</groupId>
<artifactId>spire.office.free</artifactId>
<version>5.3.1</version>
</dependency>
2. 工具类
import com.spire.doc.Document;
import com.spire.doc.documents.ImageType;
import com.spire.pdf.PdfDocument;
import com.spire.pdf.graphics.PdfImageType;
import com.spire.presentation.FileFormat;
import com.spire.presentation.Presentation;
import com.spire.xls.Workbook;
import lombok.SneakyThrows;
import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.Frame;
import org.bytedeco.javacv.Java2DFrameConverter;
import org.springframework.util.Assert;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
/**
* @description: office文档缩略图生成工具
* @author: Mr.404
* @create: 2024-12-13 15:08
**/
public class SpireThumbnailUtil {
// 定义日期时间格式化字符串,用于生成时间戳部分的文件名
private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");
private static String buildPicPath(File file, String fileType) {
String fileBasePath = file.getParent() + File.separator;
String timestamp = LocalDateTime.now().format(DATE_TIME_FORMATTER);
return String.format("%s%s-%s-%s.png", fileBasePath, timestamp, fileType,
file.getName().substring(0, file.getName().lastIndexOf(".")));
}
@SneakyThrows
public static String wordToImage(File wordFile) {
Document word = new Document(wordFile.getAbsolutePath());
System.out.println("word.getPageCount() = " + word.getBuiltinDocumentProperties().getPageCount());
BufferedImage image = word.saveToImages(0, ImageType.Bitmap);
String imgUrl = buildPicPath(wordFile, "word");
File file = new File(imgUrl);
ImageIO.write(image, "PNG", file);
System.out.println("word imgUrl:" + imgUrl);
return imgUrl;
}
@SneakyThrows
public static String pdfToImage(File pdfFile) {
PdfDocument pdf = new PdfDocument(pdfFile.getAbsolutePath());
System.out.println("pdf.getPages().getCount() = " + pdf.getPages().getCount());
BufferedImage image = pdf.saveAsImage(0, PdfImageType.Bitmap);
String imgUrl = buildPicPath(pdfFile, "pdf");
File file = new File(imgUrl);
ImageIO.write(image, "PNG", file);
System.out.println("pdf imgUrl:" + imgUrl);
return imgUrl;
}
@SneakyThrows
public static String excelToImage(File excelFile) {
Workbook workbook = new Workbook();
workbook.loadFromFile(excelFile.getAbsolutePath());
System.out.println("workbook.getWorksheets().getCount() = " + workbook.getWorksheets().getCount());
BufferedImage image = workbook.saveAsImage(0, 100, 100);
int maxWidth = image.getWidth();
System.out.println("maxWidth = " + maxWidth);
int maxHeight = image.getHeight();
System.out.println("maxHeight = " + maxHeight);
BufferedImage subimage = image.getSubimage(0, 0, Math.min(maxWidth, 1280), Math.min(maxHeight, 1500));
String imgUrl = buildPicPath(excelFile, "excel");
ImageIO.write(subimage, "PNG", new File(imgUrl));
workbook.dispose();
System.out.println("excel imgUrl:" + imgUrl);
return imgUrl;
}
@SneakyThrows
public static String pptToImage(File pptFile) {
Presentation ppt = new Presentation(pptFile.getAbsolutePath(), FileFormat.AUTO);
System.out.println("ppt.getSlides().size() = " + ppt.getSlides().size());
BufferedImage image = ppt.getSlides().get(0).saveAsImage();
String imgUrl = buildPicPath(pptFile, "ppt");
ImageIO.write(image, "PNG", new File(imgUrl));
ppt.dispose();
System.out.println("ppt imgUrl:" + imgUrl);
return imgUrl;
}
@SneakyThrows
public static String videoImage(File videoFile) {
String imgUrl = buildPicPath(videoFile, "video");
FFmpegFrameGrabber grabber = FFmpegFrameGrabber.createDefault(videoFile);
grabber.start();
// 获取第一帧
Frame frame = grabber.grabImage();
// 获取视频的总时长(单位:微秒)
long videoDurationInMicroSeconds = grabber.getLengthInTime();
// 将微秒转换为秒
long videoDurationInSeconds = videoDurationInMicroSeconds / 1000000;
// 输出视频时长
System.out.println("Video Duration: " + videoDurationInSeconds + " seconds");
// 将 Frame 转换为 BufferedImage
if (frame == null) {
return "";
}
// 将帧转为 BufferedImage
BufferedImage bufferedImage = new Java2DFrameConverter().getBufferedImage(frame);
File output = new File(imgUrl);
ImageIO.write(bufferedImage, "PNG", output);
grabber.stop();
return imgUrl;
}
public static String generateThumbnail(String filePath) {
File file = new File(filePath);
Assert.isTrue(file.exists(), "文件不存在");
String picPath = "";
if (filePath.endsWith("doc") || filePath.endsWith("docx")) {
picPath = wordToImage(file);
} else if (filePath.endsWith("pdf")) {
picPath = pdfToImage(file);
} else if (filePath.endsWith("xlsx") || filePath.endsWith("xls")) {
picPath = excelToImage(file);
} else if (filePath.endsWith("ppt") || filePath.endsWith("pptx")) {
picPath = pptToImage(file);
} else if (filePath.endsWith("mp4") || filePath.endsWith("avi")) {
picPath = videoImage(file);
}
return picPath;
}
public static void main(String[] args) throws Exception {
generateThumbnail("D:\\tmp\\1.docx");
generateThumbnail("D:\\tmp\\1.pdf");
generateThumbnail("D:\\tmp\\1.xlsx");
generateThumbnail("D:\\tmp\\1.pptx");
generateThumbnail("D:\\tmp\\1.mp4");
generateThumbnail("D:\\tmp\\1.avi");
}
}