java根据word模板生成word,在根据word文件转换成pdf文件

1.引入pom文件

  <!-- Apache POI for Word document generation -->
       <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>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-scratchpad</artifactId>
            <version>5.2.3</version>
        </dependency>

        <!-- Apache POI PDF Converter -->
        <dependency>
            <groupId>fr.opensagres.xdocreport</groupId>
            <artifactId>fr.opensagres.xdocreport.converter.docx.xwpf</artifactId>
            <version>2.0.6</version>
        </dependency>

2.Word模板使用说明

在`src/main/resources/templates/`(自定义)目录下放置Word模板文件,例如`rectification_template.docx`。

在模板中使用占位符格式:`${字段名}`,例如:
- `${safe}` 
- `${quality}` 

当调用接口时,系统会根据模板和数据生成新的Word文档

image

 

 

3.代码

    @ApiOperation("预览PDF文档")
    @GetMapping("/previewPdfDocument/{id}")
    public void previewPdfDocument(@PathVariable Long id, HttpServletResponse response) {
        try {
            // 生成PDF文档文件
            File pdfFile = rectificationService.generatePdfDocumentFile(id);

            if (pdfFile == null) {
                response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "PDF文档生成失败");
                return;
            }

            // 设置响应头,使浏览器直接预览而不是下载
            response.setContentType("application/pdf");
            response.setContentLength((int) pdfFile.length());

            // 写入响应
            try (FileInputStream fileInputStream = new FileInputStream(pdfFile);
                 ServletOutputStream outputStream = response.getOutputStream()) {

                byte[] buffer = new byte[1024];
                int bytesRead;
                while ((bytesRead = fileInputStream.read(buffer)) != -1) {
                    outputStream.write(buffer, 0, bytesRead);
                }
                outputStream.flush();
            }

            // 删除临时文件
            pdfFile.delete();
        } catch (Exception e) {
            try {
                response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "PDF文档生成或预览过程中发生错误: " + e.getMessage());
            } catch (IOException ioException) {
                ioException.printStackTrace();
            }
        }
    }

4.代码2

   @Override
    public File generatePdfDocumentFile(Long id) {
        try {
            // 首先生成Word文档
            ByteArrayOutputStream wordOutputStream = generatePdf(id);
            if (wordOutputStream == null) {
                return null;
            }

            // 创建临时文件
            File pdfFile = File.createTempFile("rectification_" + id + "_", ".pdf");
            
            // 将Word转换为PDF并写入文件
            try (ByteArrayInputStream wordInputStream = new ByteArrayInputStream(wordOutputStream.toByteArray());
                 FileOutputStream pdfOutputStream = new FileOutputStream(pdfFile)) {
                
                PdfUtil.convertWordToPdfFormatted(wordInputStream, pdfOutputStream);
                return pdfFile;
            }
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

5.模板数据填入

  @Override
    public ByteArrayOutputStream generatePdf(Long id) {
        Intion entity = baseMapper.selectById(id);//改成自己需要的数据
        if (null == entity) {
            return null;
        }
        //模板路径
        ClassPathResource resource = new ClassPathResource("templates/rectification_template.docx");
        // 准备模板数据
        Map<String, Object> dataMap = new HashMap<>();
        dataMap.put("safe", entity.getSafe());

        try {
            // 获取模板路径
            String templatePath = resource.getFile().getAbsolutePath();

            // 生成Word文档
            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
            WordTemplateUtil.generateWordFromTemplate(templatePath, dataMap, outputStream);

            return outputStream;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

6.word工具类

import org.apache.poi.xwpf.usermodel.*;
import java.io.*;
import java.util.Map;
import java.util.List;

/**
 * Word模板工具类
 * 根据Word模板生成带数据的Word文档
 */
public class WordTemplateUtil {

    /**
     * 根据模板生成Word文档
     * @param templatePath 模板文件路径
     * @param params 数据参数
     * @param outputStream 输出流
     * @throws IOException IO异常
     */
    public static void generateWordFromTemplate(String templatePath, Map<String, Object> params, OutputStream outputStream) throws IOException {
        try (FileInputStream fis = new FileInputStream(templatePath);
             XWPFDocument document = new XWPFDocument(fis)) {
            
            // 替换段落中的占位符
            replaceInParagraphs(document, params);
            
            // 替换表格中的占位符
            replaceInTables(document, params);
            
            // 写入输出流
            document.write(outputStream);
        }
    }
    
    /**
     * 替换段落中的占位符
     * @param document Word文档
     * @param params 参数映射
     */
    private static void replaceInParagraphs(XWPFDocument document, Map<String, Object> params) {
        for (XWPFParagraph paragraph : document.getParagraphs()) {
            for (XWPFRun run : paragraph.getRuns()) {
                String text = run.getText(0);
                if (text != null) {
                    for (Map.Entry<String, Object> entry : params.entrySet()) {
                        String placeholder = "${" + entry.getKey() + "}";
                        Object value = entry.getValue();
                        
                        if (text.contains(placeholder)) {
                            text = text.replace(placeholder, value != null ? value.toString() : "");
                            run.setText(text, 0);
                        }
                    }
                }
            }
        }
    }
    
    /**
     * 替换表格中的占位符
     * @param document Word文档
     * @param params 参数映射
     */
    private static void replaceInTables(XWPFDocument document, Map<String, Object> params) {
        for (XWPFTable table : document.getTables()) {
            for (XWPFTableRow row : table.getRows()) {
                for (XWPFTableCell cell : row.getTableCells()) {
                    for (XWPFParagraph paragraph : cell.getParagraphs()) {
                        for (XWPFRun run : paragraph.getRuns()) {
                            String text = run.getText(0);
                            if (text != null) {
                                for (Map.Entry<String, Object> entry : params.entrySet()) {
                                    String placeholder = "${" + entry.getKey() + "}";
                                    Object value = entry.getValue();
                                    
                                    if (text.contains(placeholder)) {
                                        text = text.replace(placeholder, value != null ? value.toString() : "");
                                        run.setText(text, 0);
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
    
    /**
     * 生成表格数据
     * @param document Word文档
     * @param bookmark 表格书签
     * @param headers 表头
     * @param dataList 数据列表
     */
    public static void generateTableData(XWPFDocument document, String bookmark, String[] headers, List<Object[]> dataList) {
        // 查找书签位置
        // 这里简化处理,实际应用中可以通过查找书签位置来确定表格插入点
        
        // 创建表格
        XWPFTable table = document.createTable();
        
        // 设置表头
        XWPFTableRow headerRow = table.getRow(0);
        for (int i = 0; i < headers.length; i++) {
            if (i == 0) {
                headerRow.getCell(0).setText(headers[i]);
            } else {
                headerRow.addNewTableCell().setText(headers[i]);
            }
        }
        
        // 填充数据
        for (Object[] rowData : dataList) {
            XWPFTableRow row = table.createRow();
            for (int i = 0; i < rowData.length; i++) {
                row.getCell(i).setText(rowData[i] != null ? rowData[i].toString() : "");
            }
        }
    }
}

7.pdf 工具类

import org.apache.poi.xwpf.usermodel.XWPFDocument;
import fr.opensagres.poi.xwpf.converter.pdf.PdfConverter;
import fr.opensagres.poi.xwpf.converter.pdf.PdfOptions;

import java.io.InputStream;
import java.io.OutputStream;
import java.io.IOException;

/**
 * PDF工具类
 * 提供Word转PDF等功能
 */
public class PdfUtil {

    
    /**
     * 将Word文档转换为PDF (使用Apache POI实现)
     * 使用org.apache.poi.xwpf.usermodel.XWPFDocument和fr.opensagres.poi.xwpf.converter.pdf实现转换
     * @param wordInputStream Word文档输入流
     * @param pdfOutputStream PDF文档输出流
     * @throws Exception 转换异常
     */
    public static void convertWordToPdfFormatted(InputStream wordInputStream, OutputStream pdfOutputStream) throws Exception {
        try {
            // 使用Apache POI加载Word文档
            XWPFDocument document = new XWPFDocument(wordInputStream);
            
            // 创建PDF转换选项
            PdfOptions options = PdfOptions.create();
            
            // 执行转换
            PdfConverter.getInstance().convert(document, pdfOutputStream, options);
        } catch (IOException e) {
            throw new Exception("转换Word为PDF失败", e);
        }
    }
}

 

posted @ 2025-11-18 16:50  三苇渡江  阅读(5)  评论(0)    收藏  举报