本文目录导读:

我来提供一个完整的Java实现Office转PDF的案例,包括Word、Excel和PowerPoint的转换。
方案选择
主要有以下几种方案:
- Apache POI + OpenOffice/LibreOffice - 免费开源
- Aspose - 商业但效果好
- JODConverter - 基于OpenOffice
这里我提供最常用的Apache POI + LibreOffice方案和Aspose方案。
基于LibreOffice(免费开源)
添加依赖
<dependencies>
<!-- Apache POI 用于读取Office文件 -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>5.2.3</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>5.2.3</version>
</dependency>
<!-- JODConverter 用于调用LibreOffice -->
<dependency>
<groupId>org.jodconverter</groupId>
<artifactId>jodconverter-local</artifactId>
<version>4.4.6</version>
</dependency>
<dependency>
<groupId>org.jodconverter</groupId>
<artifactId>jodconverter-core</artifactId>
<version>4.4.6</version>
</dependency>
</dependencies>
转换工具类
package com.example.officeconverter;
import org.jodconverter.local.LocalConverter;
import org.jodconverter.local.office.LocalOfficeManager;
import org.jodconverter.core.office.OfficeManager;
import org.jodconverter.core.office.OfficeException;
import org.jodconverter.core.DocumentConverter;
import java.io.File;
import java.util.UUID;
public class OfficeToPdfConverter {
private static OfficeManager officeManager;
static {
// 初始化Office管理器
try {
officeManager = LocalOfficeManager.builder()
.install()
.portNumbers(2002) // 使用固定端口
.officeHome("C:/Program Files/LibreOffice") // LibreOffice安装路径
.build();
officeManager.start();
} catch (OfficeException e) {
e.printStackTrace();
}
}
/**
* 转换Office文件为PDF
* @param sourcePath 源文件路径
* @param targetPath 目标PDF路径
* @return 转换后的PDF文件路径
*/
public static String convertToPdf(String sourcePath, String targetPath) {
try {
File sourceFile = new File(sourcePath);
File targetFile = new File(targetPath);
if (!sourceFile.exists()) {
throw new RuntimeException("源文件不存在: " + sourcePath);
}
// 创建目标目录
if (!targetFile.getParentFile().exists()) {
targetFile.getParentFile().mkdirs();
}
// 转换文档
DocumentConverter converter = LocalConverter.make();
converter.convert(sourceFile).to(targetFile).execute();
return targetPath;
} catch (OfficeException e) {
throw new RuntimeException("Office转PDF失败: " + e.getMessage(), e);
}
}
/**
* 转换并生成随机文件名
*/
public static String convertToPdf(String sourcePath) {
String targetPath = "converted_" + UUID.randomUUID().toString() + ".pdf";
return convertToPdf(sourcePath, targetPath);
}
/**
* 关闭Office管理器
*/
public static void close() {
try {
if (officeManager != null) {
officeManager.stop();
}
} catch (OfficeException e) {
e.printStackTrace();
}
}
}
测试类
package com.example.officeconverter;
public class ConverterTest {
public static void main(String[] args) {
try {
// Word转PDF
String wordPath = "D:\\test\\document.docx";
String wordPdfPath = "D:\\test\\document.pdf";
OfficeToPdfConverter.convertToPdf(wordPath, wordPdfPath);
System.out.println("Word文档转换成功!");
// Excel转PDF
String excelPath = "D:\\test\\spreadsheet.xlsx";
String excelPdfPath = "D:\\test\\spreadsheet.pdf";
OfficeToPdfConverter.convertToPdf(excelPath, excelPdfPath);
System.out.println("Excel表格转换成功!");
// PowerPoint转PDF
String pptPath = "D:\\test\\presentation.pptx";
String pptPdfPath = "D:\\test\\presentation.pdf";
OfficeToPdfConverter.convertToPdf(pptPath, pptPdfPath);
System.out.println("PowerPoint转换成功!");
} catch (Exception e) {
e.printStackTrace();
} finally {
// 最后关闭Office管理器
OfficeToPdfConverter.close();
}
}
}
基于Aspose(商业方案)
添加依赖
<dependencies>
<!-- Aspose Words for Word -->
<dependency>
<groupId>com.aspose</groupId>
<artifactId>aspose-words</artifactId>
<version>22.10</version>
<classifier>jdk11</classifier>
</dependency>
<!-- Aspose Cells for Excel -->
<dependency>
<groupId>com.aspose</groupId>
<artifactId>aspose-cells</artifactId>
<version>22.10</version>
</dependency>
<!-- Aspose Slides for PowerPoint -->
<dependency>
<groupId>com.aspose</groupId>
<artifactId>aspose-slides</artifactId>
<version>22.10</version>
<classifier>jdk16</classifier>
</dependency>
</dependencies>
具体实现
package com.example.asposeconverter;
import com.aspose.cells.Workbook;
import com.aspose.slides.Presentation;
import com.aspose.words.Document;
import com.aspose.words.SaveFormat;
public class AsposeConverter {
// 需要设置许可证,否则会有水印
static {
try {
// 设置许可证(如有)
// License license = new License();
// license.setLicense("Aspose.Total.Java.lic");
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* Word转PDF
*/
public static void wordToPdf(String sourcePath, String targetPath) throws Exception {
Document doc = new Document(sourcePath);
doc.save(targetPath, SaveFormat.PDF);
}
/**
* Excel转PDF
*/
public static void excelToPdf(String sourcePath, String targetPath) throws Exception {
Workbook workbook = new Workbook(sourcePath);
workbook.save(targetPath, com.aspose.cells.SaveFormat.PDF);
}
/**
* PowerPoint转PDF
*/
public static void pptToPdf(String sourcePath, String targetPath) throws Exception {
Presentation pres = new Presentation(sourcePath);
try {
pres.save(targetPath, com.aspose.slides.SaveFormat.Pdf);
} finally {
if (pres != null) {
pres.dispose();
}
}
}
/**
* 根据文件类型自动转换
*/
public static void convertToPdf(String sourcePath, String targetPath) throws Exception {
String extension = sourcePath.substring(sourcePath.lastIndexOf(".")).toLowerCase();
switch (extension) {
case ".doc":
case ".docx":
wordToPdf(sourcePath, targetPath);
break;
case ".xls":
case ".xlsx":
excelToPdf(sourcePath, targetPath);
break;
case ".ppt":
case ".pptx":
pptToPdf(sourcePath, targetPath);
break;
default:
throw new IllegalArgumentException("不支持的文件格式: " + extension);
}
}
}
测试类
package com.example.asposeconverter;
public class AsposeTest {
public static void main(String[] args) {
try {
// Word转PDF
AsposeConverter.convertToPdf(
"D:\\test\\report.docx",
"D:\\test\\report.pdf"
);
System.out.println("Word转换成功");
// Excel转PDF
AsposeConverter.convertToPdf(
"D:\\test\\data.xlsx",
"D:\\test\\data.pdf"
);
System.out.println("Excel转换成功");
// PPT转PDF
AsposeConverter.convertToPdf(
"D:\\test\\slides.pptx",
"D:\\test\\slides.pdf"
);
System.out.println("PPT转换成功");
} catch (Exception e) {
e.printStackTrace();
}
}
}
Web服务实现(Spring Boot)
package com.example.controller;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.UUID;
@RestController
@RequestMapping("/api/converter")
public class FileConverterController {
private static final String UPLOAD_DIR = "D:/temp/upload/";
private static final String CONVERTED_DIR = "D:/temp/converted/";
/**
* 上传并转换Office文件
*/
@PostMapping("/toPdf")
public ResponseEntity<?> convertToPdf(@RequestParam("file") MultipartFile file) {
try {
// 创建临时目录
Files.createDirectories(Paths.get(UPLOAD_DIR));
Files.createDirectories(Paths.get(CONVERTED_DIR));
// 保存上传的文件
String originalFilename = file.getOriginalFilename();
String extension = getExtension(originalFilename);
String fileName = UUID.randomUUID() + extension;
String uploadPath = UPLOAD_DIR + fileName;
File uploadedFile = new File(uploadPath);
file.transferTo(uploadedFile);
// 转换文件
String pdfFileName = UUID.randomUUID() + ".pdf";
String pdfPath = CONVERTED_DIR + pdfFileName;
OfficeToPdfConverter.convertToPdf(uploadPath, pdfPath);
// 返回下载链接
String downloadUrl = "/api/converter/download/" + pdfFileName;
// 清理上传文件
uploadedFile.delete();
return ResponseEntity.ok()
.body(java.util.Map.of(
"status", "success",
"message", "转换成功",
"downloadUrl", downloadUrl
));
} catch (Exception e) {
return ResponseEntity.badRequest()
.body(java.util.Map.of(
"status", "error",
"message", "转换失败: " + e.getMessage()
));
}
}
/**
* 下载转换后的PDF
*/
@GetMapping("/download/{filename}")
public ResponseEntity<byte[]> downloadFile(@PathVariable String filename) {
try {
Path filePath = Paths.get(CONVERTED_DIR + filename);
if (Files.exists(filePath)) {
byte[] content = Files.readAllBytes(filePath);
return ResponseEntity.ok()
.header("Content-Type", "application/pdf")
.header("Content-Disposition", "attachment; filename=\"" + filename + "\"")
.body(content);
} else {
return ResponseEntity.notFound().build();
}
} catch (IOException e) {
return ResponseEntity.status(500).build();
}
}
private String getExtension(String filename) {
return filename.substring(filename.lastIndexOf(".")).toLowerCase();
}
}
性能优化建议
public class ConverterOptimizer {
// 1. 使用线程池处理并发转换
private static ExecutorService executor = Executors.newFixedThreadPool(10);
// 2. 异步转换
public static CompletableFuture<String> asyncConvert(String sourcePath, String targetPath) {
return CompletableFuture.supplyAsync(() -> {
try {
OfficeToPdfConverter.convertToPdf(sourcePath, targetPath);
return targetPath;
} catch (Exception e) {
throw new RuntimeException(e);
}
}, executor);
}
// 3. 批量转换
public static List<String> batchConvert(List<String> sourcePaths, String targetDir) {
List<CompletableFuture<String>> futures = new ArrayList<>();
for (String sourcePath : sourcePaths) {
String targetPath = targetDir + UUID.randomUUID() + ".pdf";
futures.add(asyncConvert(sourcePath, targetPath));
}
// 等待所有转换完成
return futures.stream()
.map(CompletableFuture::join)
.collect(Collectors.toList());
}
// 4. 文件清理
public static void cleanupOldFiles(String dir, long maxAgeInMillis) {
File directory = new File(dir);
File[] files = directory.listFiles();
if (files != null) {
long now = System.currentTimeMillis();
for (File file : files) {
if (now - file.lastModified() > maxAgeInMillis) {
file.delete();
}
}
}
}
}
注意事项
-
LibreOffice方案:
- 需要安装LibreOffice
- 转换质量取决于LibreOffice的兼容性
- 适合免费开源项目
-
Aspose方案:
- 效果最好,格式兼容性最高
- 需要购买许可证
- 适合企业级应用
-
通用建议:
- 处理好异常和日志
- 考虑内存限制
- 实现文件清理机制
- 注意并发和资源管理
选择哪种方案取决于你的具体需求、预算和使用场景,如果需要更详细的实现或特定功能的扩展,请告诉我。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播