Java实现Office转PDF案例

wen java案例 2

本文目录导读:

Java实现Office转PDF案例

  1. 方案选择
  2. 方案一:基于LibreOffice(免费开源)
  3. 方案二:基于Aspose(商业方案)
  4. 方案三:Web服务实现(Spring Boot)
  5. 性能优化建议
  6. 注意事项

我来提供一个完整的Java实现Office转PDF的案例,包括Word、Excel和PowerPoint的转换。

方案选择

主要有以下几种方案:

  1. Apache POI + OpenOffice/LibreOffice - 免费开源
  2. Aspose - 商业但效果好
  3. 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();
                }
            }
        }
    }
}

注意事项

  1. LibreOffice方案

    • 需要安装LibreOffice
    • 转换质量取决于LibreOffice的兼容性
    • 适合免费开源项目
  2. Aspose方案

    • 效果最好,格式兼容性最高
    • 需要购买许可证
    • 适合企业级应用
  3. 通用建议

    • 处理好异常和日志
    • 考虑内存限制
    • 实现文件清理机制
    • 注意并发和资源管理

选择哪种方案取决于你的具体需求、预算和使用场景,如果需要更详细的实现或特定功能的扩展,请告诉我。

抱歉,评论功能暂时关闭!