DocumentCreator.java 8.7 KB
package com.aigeo.util;

import org.apache.poi.util.Units;
import org.apache.poi.xwpf.usermodel.ParagraphAlignment;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.apache.poi.xwpf.usermodel.XWPFRun;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTInd;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTPPr;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTSpacing;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.STLineSpacingRule;

import java.io.FileOutputStream;
import java.io.InputStream;
import java.math.BigInteger;
import java.net.URL;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class DocumentCreator {
    public static String create(String content) {
        try {
            //生成一个随机文件名称
            long l = System.currentTimeMillis();
            String fileName = "D:/LsYwxProject/YwxErpApi/yiwaixiaoerp/YwxErp/upload/aidocx/" + l + ".docx";
            createFormattedDocx(content, fileName);
            System.out.println("文档创建成功:自然的诗篇.docx");
            return fileName;
        } catch (Exception e) {
            System.err.println("创建文档时出错: " + e.getMessage());
            e.printStackTrace();
            return null;
        }
    }

    public static void createFormattedDocx(String content, String fileName) throws Exception {
        // 创建新文档
        XWPFDocument document = new XWPFDocument();

        // 按换行符分割内容
        String[] parts = content.split("\n\n");

        if (parts.length == 0) return;

        // 处理标题(第一部分)
        String title = parts[0];
        // 移除标题前的Markdown标记
        if (title.startsWith("# ")) {
            title = title.substring(2);
        }
        createHeading(document, title, 1);

        // 处理其余部分
        for (int i = 1; i < parts.length; i++) {
            String part = parts[i];

            // 检查是否是图片标记
            if (part.startsWith("![")) {
                String imageUrl = extractImageUrl(part);
                if (imageUrl != null) {
                    // 下载并插入图片
                    insertImage(document, imageUrl);
                }
            } else {
                // 处理普通文本段落
                createFormattedParagraph(document, part);
            }
        }

        // 保存文件
        try (FileOutputStream out = new FileOutputStream(fileName)) {
            document.write(out);
        }
    }

    // 从Markdown图片标记中提取URL
    private static String extractImageUrl(String markdown) {
        // 正则表达式匹配Markdown图片语法
        Pattern pattern = Pattern.compile("!\\[.*?\\]\\((.*?)\\)");
        Matcher matcher = pattern.matcher(markdown);
        if (matcher.find()) {
            return matcher.group(1);
        }
        return null;
    }

    // 下载并插入图片
    private static void insertImage(XWPFDocument doc, String imageUrl) throws Exception {
        try {
            // 创建新段落用于放置图片
            XWPFParagraph para = doc.createParagraph();
            para.setAlignment(ParagraphAlignment.CENTER);
            XWPFRun run = para.createRun();

            // 下载图片
            URL url = new URL(imageUrl);
            try (InputStream is = url.openStream()) {
                // 插入图片(宽度15厘米,高度按比例自动计算)
                run.addPicture(is,
                        XWPFDocument.PICTURE_TYPE_JPEG,
                        "image.jpg",
                        Units.toEMU(400),  // 宽度15厘米
                        Units.toEMU(200)); // 高度10厘米(实际会按比例调整)
            }

            // 添加图片标题(可选)
            //XWPFParagraph caption = doc.createParagraph();
            //caption.setAlignment(ParagraphAlignment.CENTER);
            //XWPFRun captionRun = caption.createRun();
            //captionRun.setText("自然的画卷");
            //captionRun.setFontSize(10);
            //captionRun.setFontFamily("宋体");
            //captionRun.setItalic(true);

        } catch (Exception e) {
            System.err.println("无法插入图片: " + e.getMessage());
            // 创建错误信息段落
            XWPFParagraph errorPara = doc.createParagraph();
            XWPFRun errorRun = errorPara.createRun();
            errorRun.setText("[图片加载失败: " + imageUrl + "]");
            errorRun.setColor("FF0000");
        }
    }

    // 创建标题方法
    private static void createHeading(XWPFDocument doc, String text, int level) {
        XWPFParagraph heading = doc.createParagraph();
        heading.setStyle("Heading" + level);

        XWPFRun run = heading.createRun();
        run.setText(text);
        run.setBold(true);
        run.setFontSize(18);
        run.setFontFamily("楷体");

        // 设置标题居中
        heading.setAlignment(ParagraphAlignment.CENTER);

        // 设置段后间距
        CTPPr ppr = heading.getCTP().getPPr();
        if (ppr == null) ppr = heading.getCTP().addNewPPr();
        CTSpacing spacing = ppr.isSetSpacing() ? ppr.getSpacing() : ppr.addNewSpacing();
        spacing.setAfter(BigInteger.valueOf(400)); // 20磅间距
    }

    // 创建格式化的正文段落
    private static void createFormattedParagraph(XWPFDocument doc, String text) {
        XWPFParagraph para = doc.createParagraph();
        XWPFRun run = para.createRun();
        run.setText(text);
        run.setFontSize(12);
        run.setFontFamily("宋体");

        // 设置首行缩进和行距
        CTPPr ppr = para.getCTP().getPPr();
        if (ppr == null) ppr = para.getCTP().addNewPPr();

        // 首行缩进2字符 (1字符=400)
        CTInd ind = ppr.isSetInd() ? ppr.getInd() : ppr.addNewInd();
        ind.setFirstLine(BigInteger.valueOf(800));

        // 设置行距 (1.5倍行距)
        CTSpacing spacing = ppr.isSetSpacing() ? ppr.getSpacing() : ppr.addNewSpacing();
        spacing.setLineRule(STLineSpacingRule.AUTO);
        spacing.setLine(BigInteger.valueOf(360)); // 1.5倍行距 = 1.5*240=360

        // 设置段后间距
        spacing.setAfter(BigInteger.valueOf(100)); // 5磅段落间距
    }

    // 下载并插入图片
    //private static void insertImage(XWPFDocument doc, String imageUrl) throws Exception {
    //    try {
    //        // 创建新段落用于放置图片
    //        XWPFParagraph para = doc.createParagraph();
    //        para.setAlignment(ParagraphAlignment.CENTER);
    //        XWPFRun run = para.createRun();
    //
    //        // 下载图片并获取原始尺寸
    //        URL url = new URL(imageUrl);
    //        try (InputStream is = url.openStream()) {
    //            // 将输入流转换为字节数组,以便多次使用
    //            byte[] imageBytes = IOUtils.toByteArray(is);
    //            ByteArrayInputStream bis = new ByteArrayInputStream(imageBytes);
    //
    //            // 获取图片尺寸
    //            BufferedImage bufferedImage = ImageIO.read(bis);
    //            if (bufferedImage != null) {
    //                int originalWidth = bufferedImage.getWidth();
    //                int originalHeight = bufferedImage.getHeight();
    //
    //                // 重置bis以供图片插入使用
    //                bis.reset();
    //                bis = new ByteArrayInputStream(imageBytes);
    //
    //                // 插入图片(使用原始宽高,转换为EMU单位)
    //                run.addPicture(new ByteArrayInputStream(imageBytes),
    //                        XWPFDocument.PICTURE_TYPE_JPEG,
    //                        "image.jpg",
    //                        Units.toEMU(400),  // 宽度15厘米
    //                        Units.toEMU(200)); // 高度10厘米
    //            } else {
    //                // 如果无法获取尺寸,使用默认尺寸
    //                run.addPicture(new ByteArrayInputStream(imageBytes),
    //                        XWPFDocument.PICTURE_TYPE_JPEG,
    //                        "image.jpg",
    //                        Units.toEMU(400),  // 宽度15厘米
    //                        Units.toEMU(200)); // 高度10厘米
    //            }
    //        }
    //
    //    } catch (Exception e) {
    //        System.err.println("无法插入图片: " + e.getMessage());
    //        // 创建错误信息段落
    //        XWPFParagraph errorPara = doc.createParagraph();
    //        XWPFRun errorRun = errorPara.createRun();
    //        errorRun.setText("[图片加载失败: " + imageUrl + "]");
    //        errorRun.setColor("FF0000");
    //    }
    //}
}