Files
DoLuEdu-WordFileParse/java-src/utils/WordParseUtil.java
Quentin 3271fee5cc init: WordFileParse docx→HTML 解析服务(含 Word EQ 域公式修复)
服务:Spring Boot 3.2 + docx4j 8.3.9,POST /api/v3/server_office_file/file/parse
      接受 .docx,返回 HTML(公式 → LaTeX,图片 → RustFS 外链)

公式支持三类来源:
- OMML(Word 2007+ 公式)      → Python omml_mathml2latex
- MathType OLE 对象            → Ruby mathtype2mathml → MathML → LaTeX
- Word EQ 域(老教辅主力)      → EqToLatexUtil(本次新增)

本次改动:
1. 新增 java-svc/.../core/EqToLatexUtil.java:
   移植自 jby backend-services office-core,EQ 语法 → LaTeX
   (\f→\dfrac、\r→\sqrt、\i→\int/\sum/\prod、\s→^{}/_{}、\b→\left\right、
     \a→array、\x→\boxed/\overline、\o\al 堆叠、圈码、化学符号、极限、连等式)
   品牌标记 JBYU* → WPU*,与采集端一致
2. CtoMathFinder:接上 EQ 分支(原为 not-ported 桩),域代码经
   EqToLatexUtil.convert 转 LaTeX 写入 eqLatexMap(WPEQNUM 占位符)
3. WordParseUtil.dealPlaceholder:EQ 的 LaTeX 同样加 \( \) 包裹
   (原先因 WPEQNUM 例外不加包裹,前端/MathJax 不渲染)

修前症状:教辅 Word 里分式/方程组/上下标整段丢失(如 {−1/3, 1} 变成 {-,1})
修后实测:46 份教辅 2908 处 EQ 域全部还原,公式总数 2954 处、零未包裹残留

安全:application.yml(含 RustFS 密钥)不入库,提供 application.yml.example;
      OssService 的 @Value 默认密钥已清空
2026-09-29 09:43:13 +08:00

1792 lines
87 KiB
Java

/*
* Decompiled with CFR 0.152.
*
* Could not load the following classes:
* cn.hutool.core.io.FileUtil
* cn.hutool.core.util.ArrayUtil
* com.alibaba.fastjson.JSONObject
* com.alibaba.fastjson2.JSON
* com.jby.common.exceptions.BizAssert
* com.jby.common.exceptions.BusinessException
* com.jby.common.feign.FeignUtils
* com.jby.common.result.Result
* com.jby.common.util.CloseIoUtil
* com.jby.common.util.FileUtil
* com.jby.common.util.HttpClientUtil
* com.jby.common.util.SpringContextHolder
* com.jby.common.util.UniqueUtil
* com.jby.office.constant.Constants
* com.jby.office.domain.param.OfficeFileParseRecordParam
* com.jby.office.domain.vo.OfficeFileParseRecordVO
* com.jby.oss.domain.param.OssParam
* com.jby.system.enums.AttachmentModuleEnum
* javax.annotation.Nullable
* javax.xml.bind.JAXBElement
* org.apache.commons.collections4.CollectionUtils
* org.apache.commons.collections4.MapUtils
* org.apache.commons.io.FilenameUtils
* org.apache.commons.lang3.StringUtils
* org.apache.poi.ooxml.POIXMLDocumentPart
* org.apache.poi.openxml4j.util.ZipSecureFile
* org.apache.poi.xwpf.usermodel.XWPFDocument
* org.apache.poi.xwpf.usermodel.XWPFParagraph
* org.apache.poi.xwpf.usermodel.XWPFPictureData
* org.apache.xmlbeans.XmlException
* org.apache.xmlbeans.XmlObject
* org.docx4j.Docx4J
* org.docx4j.TextUtils
* org.docx4j.TraversalUtil
* org.docx4j.TraversalUtil$Callback
* org.docx4j.XmlUtils
* org.docx4j.convert.out.HTMLSettings
* org.docx4j.model.listnumbering.ListNumberingDefinition
* org.docx4j.openpackaging.packages.OpcPackage
* org.docx4j.openpackaging.packages.WordprocessingMLPackage
* org.docx4j.openpackaging.parts.WordprocessingML.MainDocumentPart
* org.docx4j.openpackaging.parts.WordprocessingML.NumberingDefinitionsPart
* org.docx4j.openpackaging.parts.WordprocessingML.StyleDefinitionsPart
* org.docx4j.wml.Body
* org.docx4j.wml.Document
* org.docx4j.wml.Lvl$LvlText
* org.docx4j.wml.P
* org.jsoup.Jsoup
* org.jsoup.nodes.Document
* org.jsoup.nodes.Element
* org.jsoup.nodes.Node
* org.jsoup.nodes.TextNode
* org.jsoup.select.Elements
* org.openxmlformats.schemas.officeDocument.x2006.math.CTOMath
* org.openxmlformats.schemas.officeDocument.x2006.math.CTOMathPara
* org.openxmlformats.schemas.wordprocessingml.x2006.main.CTP
* org.slf4j.Logger
* org.slf4j.LoggerFactory
* org.springframework.beans.BeansException
* org.springframework.beans.factory.annotation.Autowired
* org.springframework.context.ApplicationContext
* org.springframework.context.ApplicationContextAware
* org.springframework.stereotype.Component
* org.springframework.util.StopWatch
* org.springframework.util.StopWatch$TaskInfo
* org.springframework.web.multipart.MultipartFile
*/
package com.jby.officecore.utils;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.ArrayUtil;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson2.JSON;
import com.jby.common.exceptions.BizAssert;
import com.jby.common.exceptions.BusinessException;
import com.jby.common.feign.FeignUtils;
import com.jby.common.result.Result;
import com.jby.common.util.CloseIoUtil;
import com.jby.common.util.HttpClientUtil;
import com.jby.common.util.SpringContextHolder;
import com.jby.common.util.UniqueUtil;
import com.jby.office.constant.Constants;
import com.jby.office.domain.param.OfficeFileParseRecordParam;
import com.jby.office.domain.vo.OfficeFileParseRecordVO;
import com.jby.officecore.config.OfficeCoreConfig;
import com.jby.officecore.domain.bo.ImageBO;
import com.jby.officecore.domain.bo.ParseBO;
import com.jby.officecore.domain.bo.TagStyleBO;
import com.jby.officecore.domain.param.ParseParam;
import com.jby.officecore.enums.AttrEnum;
import com.jby.officecore.enums.TagEnum;
import com.jby.officecore.feign.FileServiceFeign;
import com.jby.officecore.pool.OMml2MmlTransformerPool;
import com.jby.officecore.utils.DigestUtil;
import com.jby.officecore.utils.LatexUtil;
import com.jby.officecore.utils.MathTypeUtil;
import com.jby.officecore.utils.NumPr;
import com.jby.officecore.utils.OfficeFileUtil;
import com.jby.officecore.utils.OssServiceUtil;
import com.jby.officecore.utils.WordExportUtil;
import com.jby.officecore.utils.WpsConvertUtil;
import com.jby.officecore.utils.finder.CtObjectFinder;
import com.jby.officecore.utils.finder.CtTextBoxFinder;
import com.jby.officecore.utils.finder.CtoMathFinder;
import com.jby.officecore.utils.finder.DrawingPictFinder;
import com.jby.oss.domain.param.OssParam;
import com.jby.system.enums.AttachmentModuleEnum;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.awt.image.RenderedImage;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.Closeable;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.StringReader;
import java.io.StringWriter;
import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.OpenOption;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.attribute.FileAttribute;
import java.util.AbstractMap;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Comparator;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.function.Function;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;
import javax.annotation.Nullable;
import javax.imageio.ImageIO;
import javax.imageio.ImageReader;
import javax.imageio.stream.ImageInputStream;
import javax.xml.bind.JAXBElement;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ooxml.POIXMLDocumentPart;
import org.apache.poi.openxml4j.util.ZipSecureFile;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.apache.poi.xwpf.usermodel.XWPFPictureData;
import org.apache.xmlbeans.XmlException;
import org.apache.xmlbeans.XmlObject;
import org.docx4j.Docx4J;
import org.docx4j.TextUtils;
import org.docx4j.TraversalUtil;
import org.docx4j.XmlUtils;
import org.docx4j.convert.out.HTMLSettings;
import org.docx4j.model.listnumbering.ListNumberingDefinition;
import org.docx4j.openpackaging.packages.OpcPackage;
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
import org.docx4j.openpackaging.parts.WordprocessingML.MainDocumentPart;
import org.docx4j.openpackaging.parts.WordprocessingML.NumberingDefinitionsPart;
import org.docx4j.openpackaging.parts.WordprocessingML.StyleDefinitionsPart;
import org.docx4j.wml.Body;
import org.docx4j.wml.Document;
import org.docx4j.wml.Lvl;
import org.docx4j.wml.P;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Element;
import org.jsoup.nodes.Node;
import org.jsoup.nodes.TextNode;
import org.jsoup.select.Elements;
import org.openxmlformats.schemas.officeDocument.x2006.math.CTOMath;
import org.openxmlformats.schemas.officeDocument.x2006.math.CTOMathPara;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTP;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
import org.springframework.util.StopWatch;
import org.springframework.web.multipart.MultipartFile;
@Component
public class WordParseUtil
implements ApplicationContextAware {
private static final Logger log = LoggerFactory.getLogger(WordParseUtil.class);
private static final String TEXT_PATTERN_STR = "^(?:\\s*[\u4e00-\u9fa2]{0,10}[\u4e00\u4e8c\u4e09\u56db\u4e94\u516d\u4e03\u516b\u4e5d\u5341]+(?:\u3001|\\s+).+)|(?:(?:[\u3010\u3016\\[])[\u4e00-\u9fa2]{2,20}(?:[\u3011\u3017\\]]))$";
private static final Pattern TEXT_PATTERN = Pattern.compile("^(?:\\s*[\u4e00-\u9fa2]{0,10}[\u4e00\u4e8c\u4e09\u56db\u4e94\u516d\u4e03\u516b\u4e5d\u5341]+(?:\u3001|\\s+).+)|(?:(?:[\u3010\u3016\\[])[\u4e00-\u9fa2]{2,20}(?:[\u3011\u3017\\]]))$");
private static final String MATH_PLACEHOLDER = "<w:rPr><w:rFonts w:hint=\"eastAsia\" /><w:lang w:val=\"en-US\" w:eastAsia=\"zh-CN\" /></w:rPr><w:t>%s</w:t>";
private static final String[] SYMBOL = new String[]{"\\ue0fc", "\\ue100", "\\ue101"};
private static OfficeCoreConfig officeCoreConfig;
private static FileServiceFeign fileServiceFeign;
private static ApplicationContext applicationContext;
private static volatile Executor batchDealPicExecutor;
@Autowired
public void setOfficeCoreConfig(OfficeCoreConfig officeCoreConfig) {
WordParseUtil.officeCoreConfig = officeCoreConfig;
}
@Autowired
public void setFileServiceFeign(FileServiceFeign fileServiceFeign) {
WordParseUtil.fileServiceFeign = fileServiceFeign;
}
public void setApplicationContext(@Nullable ApplicationContext ctx) throws BeansException {
applicationContext = ctx;
}
/*
* WARNING - Removed try catching itself - possible behaviour change.
* Enabled force condition propagation
* Lifted jumps to return sites
*/
private static Executor getBatchDealPicExecutor() {
if (!Objects.isNull(batchDealPicExecutor)) return batchDealPicExecutor;
Class<WordParseUtil> clazz = WordParseUtil.class;
synchronized (WordParseUtil.class) {
if (!Objects.isNull(batchDealPicExecutor)) return batchDealPicExecutor;
batchDealPicExecutor = (Executor)applicationContext.getBean("batchDealPicExecutor", Executor.class);
// ** MonitorExit[var0] (shouldn't be in output)
return batchDealPicExecutor;
}
}
public static String parseByUrl(ParseParam param) {
String fileUrl = param.getSourceUrl();
BizAssert.isNotBlank((String)fileUrl, (String)"\u6e90\u6587\u4ef6Url\u4e3a\u7a7a\uff01");
ParseBO parseBO = new ParseBO().setLatexReplaceList(param.getLatexReplaceList());
parseBO.setSourceFileUrl(fileUrl);
File sourceFile = null;
try {
WordParseUtil.createTempDir(parseBO);
String fileName = FileUtil.getName((String)fileUrl);
BizAssert.isNotBlank((String)fileName, (String)"\u6e90\u6587\u4ef6\u5730\u5740\u5f02\u5e38");
parseBO.setSourceFilePath(parseBO.getTempDir().resolve(fileName).toString());
com.jby.common.util.FileUtil.downloadNetworkFile((String)fileUrl, (String)parseBO.getSourceFilePath());
sourceFile = com.jby.common.util.FileUtil.getFile((String)parseBO.getSourceFilePath());
}
catch (Exception e) {
log.error("\u89e3\u6790\u5f02\u5e38, fileUrl:{}", (Object)fileUrl, (Object)e);
if (Objects.nonNull(parseBO.getTempDir())) {
FileUtil.del((Path)parseBO.getTempDir());
}
throw new BusinessException("\u89e3\u6790\u5f02\u5e38");
}
BizAssert.isTrue((sourceFile.length() != 0L ? 1 : 0) != 0, (String)"\u6587\u6863\u5185\u5bb9\u4e3a\u7a7a\uff01");
try {
WordParseUtil.checkSuffixAndSize(sourceFile, null);
String e = WordParseUtil.parse(parseBO);
return e;
}
catch (Exception e) {
log.error("\u89e3\u6790\u5f02\u5e38, fileUrl:{}", (Object)fileUrl, (Object)e);
throw new BusinessException("\u89e3\u6790\u5f02\u5e38");
}
finally {
if (Objects.nonNull(parseBO.getTempDir())) {
FileUtil.del((Path)parseBO.getTempDir());
}
}
}
public static String parseByFile(ParseParam param) {
MultipartFile file = param.getSourceFile();
WordParseUtil.checkSuffixAndSize(file, null);
ParseBO parseBO = new ParseBO().setLatexReplaceList(param.getLatexReplaceList()).setNewParseVersion(param.getNewParseVersion()).setFileId(param.getFileId());
try {
WordParseUtil.createTempDir(parseBO);
String fileName = file.getOriginalFilename();
BizAssert.isNotBlank((String)fileName, (String)"\u6e90\u6587\u4ef6\u5730\u5740\u5f02\u5e38");
assert (fileName != null);
parseBO.setSourceFilePath(parseBO.getTempDir().resolve(fileName).toString());
FileUtil.writeFromStream((InputStream)file.getInputStream(), (File)com.jby.common.util.FileUtil.getFile((String)parseBO.getSourceFilePath()));
String string = WordParseUtil.parse(parseBO);
return string;
}
catch (Exception e) {
log.error("\u89e3\u6790\u5f02\u5e38:{}", (Object)e.getMessage(), (Object)e);
throw new BusinessException("\u89e3\u6790\u5f02\u5e38");
}
finally {
if (Objects.nonNull(parseBO.getTempDir())) {
FileUtil.del((Path)parseBO.getTempDir());
}
}
}
public static String parse(ParseBO parseBO) {
String string;
String preHtml;
if (Boolean.TRUE.equals(officeCoreConfig.getNewParseVersion())) {
parseBO.setNewParseVersion(true);
}
String md5 = DigestUtil.getFileMd5(parseBO.getSourceFilePath());
BizAssert.isNotBlank((String)md5, (String)"\u8ba1\u7b97\u6e90\u6587\u4ef6md5\u5f02\u5e38\uff01");
parseBO.setSourceFileMd5(md5);
if (Boolean.TRUE.equals(officeCoreConfig.getOpenParseCache()) && StringUtils.isNotBlank((CharSequence)(preHtml = WordParseUtil.getFileParseResult(parseBO, md5)))) {
return preHtml;
}
if (StringUtils.isBlank((CharSequence)parseBO.getSourceFileUrl())) {
String sourceFileBakPath = parseBO.getSourceFilePath() + ".JBY_BAK";
com.jby.common.util.FileUtil.copyFile((String)parseBO.getSourceFilePath(), (String)sourceFileBakPath, (boolean)true);
parseBO.setSourceFileBakPath(sourceFileBakPath);
}
if (WordParseUtil.checkIsWps(parseBO)) {
String newSourceFilePath = WpsConvertUtil.convertFile(parseBO.getSourceFilePath(), parseBO.getTempDir().toString(), "docx", 5L);
if (StringUtils.isEmpty((CharSequence)newSourceFilePath)) {
throw new BusinessException("wps\u8f6cdocx\u5931\u8d25\uff01");
}
parseBO.setSourceFilePath(newSourceFilePath);
}
WordParseUtil.handleFormat(parseBO);
parseBO.setTransformer(OMml2MmlTransformerPool.INSTANCE.borrowObject());
FileOutputStream os = null;
try {
StopWatch sw = new StopWatch("\u89e3\u6790word");
ZipSecureFile.setMinInflateRatio((double)0.001);
sw.start("\u52a0\u8f7d\u6e90\u6587\u4ef6");
File sourceFile = com.jby.common.util.FileUtil.getFile((String)parseBO.getSourceFilePath());
WordprocessingMLPackage wordMlPackage = WordprocessingMLPackage.load((File)sourceFile);
sw.stop();
sw.start("\u81ea\u5b9a\u4e49\u89e3\u6790");
WordParseUtil.customParse(wordMlPackage, parseBO);
sw.stop();
sw.start("\u8f6c\u6362\u8bbe\u7f6e");
HTMLSettings htmlSettings = Docx4J.createHTMLSettings();
htmlSettings.setImageDirPath(parseBO.getImagesDir());
htmlSettings.setImageTargetUri("images");
htmlSettings.setOpcPackage((OpcPackage)wordMlPackage);
sw.stop();
sw.start("\u6267\u884c\u8f6c\u6362");
os = new FileOutputStream(new File(parseBO.getHtmlPath()));
Docx4J.toHTML((HTMLSettings)htmlSettings, (OutputStream)os, (int)1);
sw.stop();
sw.start("\u5904\u7406\u56fe\u7247\u4e0a\u4f20OSS\u53ca\u8f6csvg");
WordParseUtil.dealImg(parseBO);
sw.stop();
sw.start("\u5904\u7406\u6210\u5728\u7ebf\u6587\u6863\u652f\u6301\u7684html");
String html = new String(Files.readAllBytes(Paths.get(parseBO.getHtmlPath(), new String[0])), StandardCharsets.UTF_8);
html = WordParseUtil.customParseOfficeHtml(html, parseBO);
sw.stop();
WordParseUtil.saveParseResult(parseBO, html);
log.info(WordParseUtil.formatAsMillis(sw));
string = html;
}
catch (Exception e) {
try {
log.error("wordToHtml exception:{}", (Object)e.getMessage(), (Object)e);
throw new BusinessException("word\u89e3\u6790\u5f02\u5e38");
}
catch (Throwable throwable) {
CloseIoUtil.closeAll((Closeable[])new Closeable[]{os});
OMml2MmlTransformerPool.INSTANCE.returnObject(parseBO.getTransformer());
throw throwable;
}
}
CloseIoUtil.closeAll((Closeable[])new Closeable[]{os});
OMml2MmlTransformerPool.INSTANCE.returnObject(parseBO.getTransformer());
return string;
}
private static boolean checkIsWps(ParseBO parseBO) {
String sourceFilePath = parseBO.getSourceFilePath();
File file = new File(sourceFilePath);
String fileName = file.getName().toLowerCase();
String fileSuffix = com.jby.common.util.FileUtil.getFileSuffix((String)fileName);
return "wps".equals(fileSuffix);
}
private static String uploadFileToOss(File file, String module, String folderName, String fileName) {
return OssServiceUtil.uploadFile(new OssParam().setModule(module).setFolder(folderName).setFile(com.jby.common.util.FileUtil.getMultipartFile((String)fileName, (File)file)));
}
private static void customParse(WordprocessingMLPackage wordMlPackage, ParseBO parseBO) throws Exception {
NumberingDefinitionsPart numberingDefinitionsPart;
MainDocumentPart mainDocumentPart = wordMlPackage.getMainDocumentPart();
StyleDefinitionsPart styleDefinitionsPart = mainDocumentPart.getStyleDefinitionsPart();
if (Objects.nonNull(styleDefinitionsPart)) {
parseBO.setStyleDefinitionsPart(styleDefinitionsPart);
}
if (Objects.nonNull(numberingDefinitionsPart = mainDocumentPart.getNumberingDefinitionsPart())) {
HashMap numDefines = numberingDefinitionsPart.getInstanceListDefinitions();
parseBO.getNumberingDefinitionsMap().putAll(numDefines.entrySet().stream().flatMap(m1 -> ((ListNumberingDefinition)m1.getValue()).getAbstractListDefinition().getAbstractNumNode().getLvl().stream().filter(f -> Objects.nonNull(f.getStart())).map(m2 -> {
NumPr numPr = new NumPr();
numPr.setStart(m2.getStart().getVal());
numPr.setCurrent(numPr.getStart().subtract(BigInteger.ONE));
numPr.setNumFmt(Optional.ofNullable(m2.getNumFmt()).map(m -> m.getVal().toString()).orElse(""));
numPr.setLvlText(Optional.ofNullable(m2.getLvlText()).map(Lvl.LvlText::getVal).orElse(""));
return new AbstractMap.SimpleEntry<String, NumPr>((String)m1.getKey() + "_" + m2.getIlvl(), numPr);
})).collect(Collectors.toMap(AbstractMap.SimpleEntry::getKey, AbstractMap.SimpleEntry::getValue)));
}
Body body = ((Document)mainDocumentPart.getJaxbElement()).getBody();
try {
CtObjectFinder ctObjectFinder = new CtObjectFinder(wordMlPackage, parseBO);
new TraversalUtil((Object)body.getContent(), (TraversalUtil.Callback)ctObjectFinder);
MathTypeUtil.mathTypeToMathMl(parseBO.getMathTypeMap());
if (Boolean.TRUE.equals(parseBO.getNewParseVersion())) {
parseBO.getMathTypeMap().values().forEach(m -> {
m = m.replace("JBYSIMJBY", "~");
});
LatexUtil.ommlMathMlToLatexIgnoreNull(parseBO.getMathTypeMap(), officeCoreConfig.getCopyrightAddresses(), parseBO.getTempDir());
} else {
LatexUtil.mathMlToLatexIgnoreNull(parseBO.getMathTypeMap(), officeCoreConfig.getCopyrightAddresses(), parseBO.getTempDir());
}
}
catch (Exception e) {
log.error("\u81ea\u5b9a\u4e49\u89e3\u6790MathType\u516c\u5f0f\u5f02\u5e38", (Throwable)e);
}
try {
DrawingPictFinder drawingPictFinder = new DrawingPictFinder(wordMlPackage, parseBO);
new TraversalUtil((Object)body.getContent(), (TraversalUtil.Callback)drawingPictFinder);
}
catch (Exception e) {
log.error("\u81ea\u5b9a\u4e49\u89e3\u6790\u56fe\u7247\u5f02\u5e38:{}", (Object)e.getMessage(), (Object)e);
}
try {
CtoMathFinder ctoMathFinder = new CtoMathFinder(parseBO);
new TraversalUtil((Object)body.getContent(), (TraversalUtil.Callback)ctoMathFinder);
if (Boolean.TRUE.equals(parseBO.getNewParseVersion())) {
LatexUtil.ommlAndMathMlToLatex(parseBO.getOpenOfficeXmlMap(), parseBO.getTempDir());
} else {
LatexUtil.mathMlToLatex(parseBO.getOpenOfficeXmlMap(), parseBO.getTempDir());
}
}
catch (Exception e) {
log.error("\u81ea\u5b9a\u4e49\u89e3\u6790\u5fae\u8f6f\u6216\u57df\u516c\u5f0f\u5f02\u5e38", (Throwable)e);
}
try {
CtTextBoxFinder ctTextBoxFinder = new CtTextBoxFinder(wordMlPackage, parseBO);
new TraversalUtil((Object)body.getContent(), (TraversalUtil.Callback)ctTextBoxFinder);
}
catch (Exception e) {
log.error("\u81ea\u5b9a\u4e49\u89e3\u6790\u6587\u672c\u6846\u5f02\u5e38", (Throwable)e);
}
for (Object object : body.getContent()) {
List contentList;
P p;
String pText;
if (!(object instanceof P) || !StringUtils.isNotBlank((CharSequence)(pText = TextUtils.getText((Object)(p = (P)object)))) || !pText.contains("JBY_TEXTBOX_JBY") || !CollectionUtils.isNotEmpty((Collection)(contentList = p.getContent()))) continue;
ArrayList matchedItems = new ArrayList();
ArrayList unmatchedItems = new ArrayList();
for (Object obj : contentList) {
if (TextUtils.getText(obj).contains("JBY_TEXTBOX_JBY")) {
matchedItems.add(obj);
continue;
}
unmatchedItems.add(obj);
}
contentList.clear();
contentList.addAll(unmatchedItems);
contentList.addAll(matchedItems);
}
}
private static void uploadImgToOss(ParseBO parseBO) {
File folder = new File(parseBO.getImagesDir());
if (!folder.exists() || !folder.isDirectory()) {
log.info("\u672c\u5730\u6587\u4ef6\u5939\u4e0d\u5b58\u5728\u6216\u4e0d\u662f\u4e00\u4e2a\u6587\u4ef6\u5939:{}", (Object)parseBO.getImagesDir());
return;
}
Object[] files = folder.listFiles();
if (ArrayUtil.isEmpty((Object[])files)) {
return;
}
HashMap<String, String> tifFileNameMap = new HashMap<String, String>();
for (Object file : files) {
String fileName;
String suffix;
if (!((File)file).isFile() || StringUtils.isBlank((CharSequence)(suffix = FileUtil.getSuffix((String)(fileName = ((File)file).getName())))) || !"tif".equals(suffix = suffix.toLowerCase()) && !"tiff".equals(suffix)) continue;
WordParseUtil.tifToPng((File)file);
String baseName = FilenameUtils.getBaseName((String)fileName);
tifFileNameMap.put(baseName + ".png", fileName);
}
files = folder.listFiles();
assert (files != null);
for (Object file : files) {
String suffix;
if (!((File)file).isFile() || StringUtils.isBlank((CharSequence)(suffix = FileUtil.getSuffix((String)((File)file).getName())))) continue;
if ("wmf".equals(suffix = suffix.toLowerCase()) || "emf".equals(suffix)) {
byte[] fileData = new byte[]{};
try {
fileData = Files.readAllBytes(((File)file).toPath());
}
catch (IOException e) {
log.error("\u89e3\u6790\u5f02\u5e38, fileUrl:{}", (Object)((File)file).toPath(), (Object)e);
throw new BusinessException("\u89e3\u6790\u5f02\u5e38");
}
String svgUrl = OfficeFileUtil.mf2svg(new ByteArrayInputStream(fileData), parseBO.getOssFolder(), ((File)file).getName());
String tifName = (String)tifFileNameMap.get(((File)file).getName());
String imgKey = "images/" + (StringUtils.isBlank((CharSequence)tifName) ? ((File)file).getName() : tifName);
parseBO.getImgMap().put(imgKey, svgUrl);
continue;
}
if ("tif".equals(suffix) || "tiff".equals(suffix)) continue;
String imgUrl = OssServiceUtil.uploadFile(new OssParam().setModule(AttachmentModuleEnum.OFFICE_IMG.getModule()).setFolder(parseBO.getOssFolder()).setFile(com.jby.common.util.FileUtil.getMultipartFile((String)((File)file).getName(), (File)file)));
String tifName = (String)tifFileNameMap.get(((File)file).getName());
String imgKey = "images/" + (StringUtils.isBlank((CharSequence)tifName) ? ((File)file).getName() : tifName);
parseBO.getImgMap().put(imgKey, imgUrl);
}
}
/*
* WARNING - Removed try catching itself - possible behaviour change.
*/
public static File tifToPng(File tiffFile) {
File file;
File pngFile;
BufferedImage image;
ImageInputStream imageInputStream;
FileInputStream is;
block6: {
is = null;
imageInputStream = null;
is = new FileInputStream(tiffFile);
imageInputStream = ImageIO.createImageInputStream(is);
Iterator<ImageReader> readers = ImageIO.getImageReaders(imageInputStream);
if (!readers.hasNext()) {
throw new BusinessException("No suitable ImageReader found for " + tiffFile.getAbsolutePath());
}
ImageReader reader = readers.next();
reader.setInput(imageInputStream);
String baseName = FilenameUtils.getBaseName((String)tiffFile.getAbsolutePath());
String parentFolder = tiffFile.getParentFile().getAbsolutePath();
image = reader.read(0);
pngFile = new File(parentFolder, baseName + ".png");
if (image.getType() != 0 && image.getType() != 0) break block6;
boolean hasAlpha = image.getColorModel().hasAlpha();
int newType = hasAlpha ? 2 : 1;
BufferedImage convertedImage = new BufferedImage(image.getWidth(), image.getHeight(), newType);
Graphics2D graphics2D = convertedImage.createGraphics();
graphics2D.drawImage((Image)image, 0, 0, null);
graphics2D.dispose();
ImageIO.write((RenderedImage)convertedImage, "png", pngFile);
File file2 = pngFile;
CloseIoUtil.closeAll((Closeable[])new Closeable[]{imageInputStream, is});
return file2;
}
try {
ImageIO.write((RenderedImage)image, "png", pngFile);
file = pngFile;
}
catch (Exception e) {
File file3;
try {
log.error("tifToPng error:{}", (Object)e.getMessage(), (Object)e);
file3 = null;
}
catch (Throwable throwable) {
CloseIoUtil.closeAll((Closeable[])new Closeable[]{imageInputStream, is});
throw throwable;
}
CloseIoUtil.closeAll((Closeable[])new Closeable[]{imageInputStream, is});
return file3;
}
CloseIoUtil.closeAll((Closeable[])new Closeable[]{imageInputStream, is});
return file;
}
private static void customParse(XWPFDocument document, ParseBO parseBO) {
if (CollectionUtils.isEmpty((Collection)document.getParagraphs())) {
return;
}
for (XWPFParagraph paragraph : document.getParagraphs()) {
org.jsoup.nodes.Document pDocument = Jsoup.parse((String)paragraph.getCTP().xmlText());
boolean updateXml = false;
if (WordParseUtil.parseOpenOfficeXml(parseBO, paragraph, pDocument)) {
updateXml = true;
}
if (!updateXml) continue;
WordParseUtil.overrideParagraph(paragraph, pDocument);
}
LatexUtil.mathMlToLatex(parseBO.getOpenOfficeXmlMap(), parseBO.getTempDir());
}
private static boolean parseOpenOfficeXml(ParseBO parseBO, XWPFParagraph paragraph, org.jsoup.nodes.Document pDocument) {
boolean updateXml = false;
ArrayList<String> placeholderList = new ArrayList<String>();
for (CTOMathPara ctoMathPara : paragraph.getCTP().getOMathParaList()) {
for (CTOMath ctoMath : ctoMathPara.getOMathList()) {
String placeholder = parseBO.getOpenOfficeXmlPlaceholder();
parseBO.getOpenOfficeXmlMap().put(placeholder, WordParseUtil.getMathMl(ctoMath, parseBO.getTransformer()));
placeholderList.add(placeholder);
}
}
for (CTOMath ctoMath : paragraph.getCTP().getOMathList()) {
String placeholder = parseBO.getOpenOfficeXmlPlaceholder();
parseBO.getOpenOfficeXmlMap().put(placeholder, WordParseUtil.getMathMl(ctoMath, parseBO.getTransformer()));
placeholderList.add(placeholder);
}
Elements oMathElements = pDocument.getElementsByTag("m:oMath");
if (oMathElements.size() == placeholderList.size()) {
for (int i = 0; i < oMathElements.size(); ++i) {
Element element = (Element)oMathElements.get(i);
Element wr = new Element("w:r");
wr.append(String.format(MATH_PLACEHOLDER, placeholderList.get(i)));
element.replaceWith((Node)wr);
updateXml = true;
}
}
return updateXml;
}
private static boolean parseMathType(ParseBO parseBO, org.jsoup.nodes.Document pDocument) {
boolean updateXml = false;
Elements imageDataElements = pDocument.getElementsByTag("v:imagedata");
for (Element element : imageDataElements) {
String svgUrl = parseBO.getImgMap().get(element.attr("r:id"));
List<TagStyleBO> styleList = TagEnum.getStyleList(element.parent());
Map<String, String> styleMap = styleList.stream().collect(Collectors.toMap(TagStyleBO::getAttr, TagStyleBO::getValue, (l, r) -> l));
double width = WordExportUtil.getPtValue(styleMap.get(AttrEnum.WIDTH.getAttr()));
double height = WordExportUtil.getPtValue(styleMap.get(AttrEnum.HEIGHT.getAttr()));
if (!StringUtils.isNotBlank((CharSequence)svgUrl)) continue;
Element imgElement = new Element(TagEnum.IMG.getName());
imgElement.attr(AttrEnum.SRC.getAttr(), svgUrl);
imgElement.attr(AttrEnum.WIDTH.getAttr(), width + "pt");
imgElement.attr(AttrEnum.HEIGHT.getAttr(), height + "pt");
WordParseUtil.addImgAttr(imgElement);
String placeholder = parseBO.getMathTypePlaceholder();
parseBO.getMathTypeMap().put(placeholder, imgElement.outerHtml());
Element parent = element.parent().parent().parent();
Element wr = new Element("w:r");
wr.append(String.format(MATH_PLACEHOLDER, placeholder));
parent.replaceWith((Node)wr);
updateXml = true;
}
return updateXml;
}
private static void overrideParagraph(XWPFParagraph paragraph, org.jsoup.nodes.Document pDocument) {
String xml = pDocument.body().html();
try {
xml = xml.replace("&nbsp;", " ");
CTP ctp = (CTP)CTP.Factory.parse(xml);
paragraph.getCTP().set((XmlObject)ctp);
}
catch (XmlException e) {
log.error("\u91cd\u5199\u6bb5\u843d\u5f02\u5e38, xml:{}", (Object)xml, (Object)e);
}
}
public static String getMathMl(JAXBElement<?> ctoMathEle, Transformer transformer) {
String oml = XmlUtils.marshaltoString(ctoMathEle, (boolean)true, (boolean)false);
StringReader reader = new StringReader(oml);
StreamSource source = new StreamSource(reader);
return WordParseUtil.sourceToMathMl(source, transformer);
}
private static String getMathMl(CTOMath ctoMath, Transformer transformer) {
org.w3c.dom.Node node = ctoMath.getDomNode();
DOMSource source = new DOMSource(node);
return WordParseUtil.sourceToMathMl(source, transformer);
}
private static String sourceToMathMl(Source source, Transformer transformer) {
String mathMl;
StringWriter stringwriter = new StringWriter();
StreamResult result = new StreamResult(stringwriter);
try {
transformer.transform(source, result);
mathMl = stringwriter.toString();
stringwriter.close();
}
catch (Exception e) {
log.error("word\u5185\u516c\u5f0f\u89e3\u6790\u5f02\u5e38\uff1a" + e.getMessage(), (Throwable)e);
throw new BusinessException("\u516c\u5f0f\u89e3\u6790\u5f02\u5e38\uff01");
}
mathMl = mathMl.substring(mathMl.indexOf("=\"http://www.w3.org/1998/Math/MathML\""));
mathMl = "<math display=\"inline\" xmlns" + mathMl;
mathMl = mathMl.replaceAll("mml:", "");
mathMl = mathMl.replaceAll("\u00a0", "~");
return mathMl;
}
private static void parsePictures(List<XWPFPictureData> pictureList, ParseBO parseBO) {
if (CollectionUtils.isEmpty(pictureList)) {
return;
}
String folderName = parseBO.getOssFolder();
String uniquePath = officeCoreConfig.getTmpPath() + File.separator + folderName;
for (XWPFPictureData picture : pictureList) {
String suffix;
if (ArrayUtil.isEmpty((byte[])picture.getData()) || StringUtils.isBlank((CharSequence)picture.getFileName()) || !Constants.IMG_SET.contains(suffix = StringUtils.isBlank((CharSequence)(suffix = com.jby.common.util.FileUtil.getFileSuffix((String)picture.getFileName()))) ? "" : suffix.toLowerCase())) continue;
if ("wmf".equals(suffix) || "emf".equals(suffix)) {
String localFilePath = uniquePath + File.separator + picture.getFileName();
String svgUrl = OfficeFileUtil.mf2svg(new ByteArrayInputStream(picture.getData()), parseBO.getOssFolder(), picture.getFileName());
parseBO.getImgMap().put(picture.getParent().getRelationId((POIXMLDocumentPart)picture), svgUrl);
parseBO.getImgMap().put(picture.getFileName(), svgUrl);
continue;
}
if ("tif".equals(suffix) || "tiff".equals(suffix)) {
String fileName = picture.getFileName().substring(0, picture.getFileName().lastIndexOf(".") + 1) + "png";
String imgUrl = WordParseUtil.tif2Png(new ByteArrayInputStream(picture.getData()), folderName, fileName);
parseBO.getImgMap().put(picture.getFileName(), imgUrl);
continue;
}
String imgUrl = WordParseUtil.uploadImg(new ByteArrayInputStream(picture.getData()), folderName, picture.getFileName());
parseBO.getImgMap().put(picture.getFileName(), imgUrl);
}
}
private static String uploadImg(InputStream is, String folderName, String fileName) {
return OssServiceUtil.uploadStream(new OssParam().setModule(AttachmentModuleEnum.OFFICE_IMG.getModule()).setFolder(folderName).setFileName(fileName).setInputStream(is));
}
private static String tif2Png(InputStream is, String folderName, String fileName) {
String uniquePath = officeCoreConfig.getTmpPath() + File.separator + folderName;
String localFilePath = uniquePath + File.separator + fileName;
File file = OfficeFileUtil.writeFile(is, localFilePath);
String imgUrl = null;
if (Objects.nonNull(file)) {
imgUrl = OssServiceUtil.uploadFile(new OssParam().setModule(AttachmentModuleEnum.OFFICE_IMG.getModule()).setFolder(folderName).setFile(com.jby.common.util.FileUtil.getMultipartFile((String)fileName, (File)file)));
}
return imgUrl;
}
/*
* WARNING - Removed try catching itself - possible behaviour change.
*/
private static File tif2Png(InputStream is, String imgPath) {
try {
BufferedImage image = ImageIO.read(is);
if (image == null) {
File file = null;
return file;
}
File file = com.jby.common.util.FileUtil.getFile((String)imgPath);
ImageIO.write((RenderedImage)image, "png", file);
image.flush();
File e = file;
return e;
}
catch (Exception e) {
log.error("tif2Png exception, imgPath:{}", (Object)imgPath, (Object)e);
File file = null;
return file;
}
finally {
if (is != null) {
try {
is.close();
}
catch (IOException e) {
log.error("close error");
}
}
}
}
private static String customParseOfficeHtml(String html, ParseBO parseBO) {
html = html.replaceAll("text-decoration: underline;", "");
html = html.replaceAll("text-decoration: jby-underline;", "text-decoration: underline;");
org.jsoup.nodes.Document doc = Jsoup.parse((String)html);
doc.outputSettings().prettyPrint(false);
WordParseUtil.dealUderlineSubSup(doc);
WordParseUtil.dealTitle(doc);
WordParseUtil.dealUnderlineAndLineThrough(doc);
WordParseUtil.dealUnderline(doc);
WordParseUtil.dealCustomTextDecoration(doc);
WordParseUtil.dealLi(doc);
WordParseUtil.dealSubSup(doc);
WordParseUtil.cleanDocument(doc);
WordParseUtil.dealNoSPanWhiteSpace((Element)doc);
WordParseUtil.dealLineHeight((Element)doc);
return WordParseUtil.dealPlaceholder(parseBO, doc);
}
private static void dealUderlineSubSup(org.jsoup.nodes.Document doc) {
try {
Elements spansWithSupSub = doc.select("span:has(sup), span:has(sub)");
for (Element span : spansWithSupSub) {
String style = span.attr("style");
if (style == null || !style.contains("text-decoration: underline;")) continue;
Elements supSubElements = span.select("sup, sub");
Element previousSpan = span.previousElementSibling();
if (previousSpan == null || !"span".equals(previousSpan.tagName())) continue;
for (Element supSub : supSubElements) {
previousSpan.appendChild((Node)supSub);
}
span.remove();
}
}
catch (Exception e) {
log.error("\u5904\u7406\u5e26\u4e0b\u5212\u7ebf\u7684\u4e0a\u6807\u4e0b\u6807\u5f02\u5e38", (Throwable)e);
}
}
private static void dealLineHeight(Element doc) {
String[] patterns = new String[]{"line-height:\\s*([0-9]*\\.?[0-9]+)%", "line-height:\\s*([0-9]*\\.?[0-9]+)", "line-height:\\s*([0-9]+(?:\\.[0-9]+)?em)"};
Elements elements = doc.select("[style*=\"line-height\"]");
for (Element element : elements) {
String style;
String newStyle = style = element.attr("style");
for (String pStr : patterns) {
Pattern pattern = Pattern.compile(pStr);
Matcher matcher = pattern.matcher(newStyle);
StringBuffer sb = new StringBuffer();
while (matcher.find()) {
double lineHeightValue;
String originalValue = matcher.group(1);
try {
String numericValue = originalValue.replaceAll("[^0-9.]", "");
lineHeightValue = Double.parseDouble(numericValue);
if (pStr.contains("%")) {
lineHeightValue /= 100.0;
}
}
catch (NumberFormatException e) {
lineHeightValue = 0.0;
}
if (lineHeightValue < 2.0) {
String replacement = pStr.contains("%") ? "line-height: 200%" : (pStr.contains("em") ? "line-height: 2.0em" : "line-height: 2.0");
matcher.appendReplacement(sb, replacement);
continue;
}
matcher.appendReplacement(sb, matcher.group(0));
}
matcher.appendTail(sb);
newStyle = sb.toString();
}
if (newStyle.equals(style)) continue;
element.attr("style", newStyle);
}
}
private static void dealNoSPanWhiteSpace(Element doc) {
for (Node node : doc.childNodes()) {
if (node instanceof TextNode) {
TextNode textNode = (TextNode)node;
String text = textNode.getWholeText();
if (!text.contains("\u00a0")) continue;
StringBuilder sb = new StringBuilder();
for (int i = 0; i < text.length(); ++i) {
char c = text.charAt(i);
sb.append(c);
if (c != '\u00a0' || i == text.length() - 1 || text.charAt(i + 1) != '\u00a0') continue;
sb.append(" ");
}
text = sb.toString();
if (!textNode.parent().nodeName().equals("span")) {
Element span = new Element("span");
span.text(text);
textNode.replaceWith((Node)span);
continue;
}
textNode.text(text);
continue;
}
if (!(node instanceof Element)) continue;
WordParseUtil.dealNoSPanWhiteSpace((Element)node);
}
}
private static void dealWhiteSpace(org.jsoup.nodes.Document doc) {
try {
Elements elements = doc.select("span");
for (Element span : elements) {
WordParseUtil.processSpanContent((Node)span);
}
}
catch (Exception e) {
log.error("\u5904\u7406\u7a7a\u683c\u5f02\u5e38", (Throwable)e);
}
}
private static void processSpanContent(Node node) {
if (node.childNodeSize() > 0) {
for (Node childNode : node.childNodes()) {
WordParseUtil.processSpanContent(childNode);
}
} else if (node instanceof TextNode) {
TextNode textNode = (TextNode)node;
textNode.text(textNode.getWholeText().replaceAll(" ", "JBY_nbsp;"));
}
}
private static void dealTitle(org.jsoup.nodes.Document doc) {
try {
Map<String, List<Map<String, String>>> pStyleMap = WordParseUtil.parseCssRulesToMap(doc);
Elements elements = doc.select("p, li");
for (Element p : elements) {
String classAttr = p.attr("class");
if (!StringUtils.isNotBlank((CharSequence)classAttr)) continue;
HashMap<String, String> finalStyles = new HashMap<String, String>();
String existingStyle = p.attr("style");
HashSet<String> existingStyleKeys = new HashSet<String>();
if (StringUtils.isNotBlank((CharSequence)existingStyle)) {
String[] stylePairs;
for (String pair : stylePairs = existingStyle.split(";")) {
String[] parts = pair.split(":", 2);
if (parts.length != 2) continue;
String string = parts[0].trim();
String value = parts[1].trim();
finalStyles.put(string, value);
existingStyleKeys.add(string);
}
}
String[] classNames = classAttr.split("\\s+");
ArrayList<String> orderedClassNames = new ArrayList<String>();
block4: for (String selector : pStyleMap.keySet()) {
String className = selector.substring(1);
for (String currentClass : classNames) {
if (!className.equals(currentClass)) continue;
orderedClassNames.add(currentClass);
continue block4;
}
}
for (String className : orderedClassNames) {
if (!pStyleMap.containsKey("." + className)) continue;
List<Map<String, String>> classStyles = pStyleMap.get("." + className);
for (Map map : classStyles) {
for (Map.Entry entry : map.entrySet()) {
if (existingStyleKeys.contains(entry.getKey())) continue;
finalStyles.put((String)entry.getKey(), (String)entry.getValue());
}
}
}
if (finalStyles.isEmpty()) continue;
StringBuilder styleBuilder = new StringBuilder();
for (Map.Entry entry : finalStyles.entrySet()) {
styleBuilder.append((String)entry.getKey()).append(": ").append((String)entry.getValue()).append("; ");
}
p.attr("style", styleBuilder.toString().trim());
}
}
catch (NumberFormatException e) {
log.error("\u5904\u7406\u6807\u9898\u5f02\u5e38", (Throwable)e);
}
}
private static Map<String, List<Map<String, String>>> parseCssRulesToMap(org.jsoup.nodes.Document doc) {
Element styleElement = doc.selectFirst("style");
String cssContent = styleElement.html();
LinkedHashMap<String, List<Map<String, String>>> cssMap = new LinkedHashMap<String, List<Map<String, String>>>();
if (StringUtils.isBlank((CharSequence)cssContent)) {
return cssMap;
}
Pattern sectionPattern = Pattern.compile("/\\* PARAGRAPH STYLES \\*/(.*?)/\\* CHARACTER STYLES \\*/", 32);
Matcher sectionMatcher = sectionPattern.matcher(cssContent);
String targetContent = "";
targetContent = sectionMatcher.find() ? sectionMatcher.group(1) : cssContent;
Pattern cssRulePattern = Pattern.compile("([^\\{]+)\\{([^\\}]+)\\}");
Matcher matcher = cssRulePattern.matcher(targetContent);
ArrayList<String> selectorOrder = new ArrayList<String>();
while (matcher.find()) {
String[] propertyPairs;
String selector2 = matcher.group(1).trim();
String properties = matcher.group(2).trim();
ArrayList propertyList = new ArrayList();
for (String propertyPair : propertyPairs = properties.split(";")) {
String[] parts;
if (!StringUtils.isNotBlank((CharSequence)propertyPair) || (parts = propertyPair.split(":", 2)).length != 2) continue;
HashMap<String, String> propertyMap = new HashMap<String, String>();
String key = parts[0].trim();
String value = parts[1].trim();
propertyMap.put(key, value);
propertyList.add(propertyMap);
}
cssMap.put(selector2, propertyList);
selectorOrder.add(selector2);
}
return selectorOrder.stream().filter(selector -> selector.startsWith(".") && cssMap.containsKey(selector)).collect(Collectors.toMap(Function.identity(), cssMap::get, (existing, replacement) -> existing, LinkedHashMap::new));
}
private static void cleanDocument(org.jsoup.nodes.Document doc) {
try {
Element docElement = doc.selectFirst(".document");
if (Objects.isNull(docElement)) {
return;
}
log.info("\u53bb\u9664\u975e\u5fc5\u8981\u6837\u5f0f\u914d\u7f6e\u4fe1\u606f:{}", (Object)JSON.toJSONString(officeCoreConfig.getCleanStyleMap()));
Elements allElements = docElement.select("*");
for (Element el : allElements) {
WordParseUtil.cleanClass(el, docElement);
WordParseUtil.cleanStyle(el);
}
}
catch (Exception e) {
log.error("\u6e05\u6d01\u6587\u6863\u5f02\u5e38", (Throwable)e);
}
}
private static void cleanClass(Element el, Element docElement) {
if (el == docElement) {
return;
}
String className = Optional.ofNullable(el.className()).orElse("");
for (String retainClass : Constants.RETAIN_CLASS_VALUE_SET) {
if (!className.contains(retainClass)) continue;
return;
}
el.attributes().remove(AttrEnum.CLASS.getAttr());
}
private static void cleanStyle(Element el) {
if (MapUtils.isEmpty(officeCoreConfig.getCleanStyleMap())) {
return;
}
String oldStyle = el.attr(AttrEnum.STYLE.getAttr());
if (StringUtils.isBlank((CharSequence)oldStyle)) {
return;
}
String[] originalStyle = new String[]{oldStyle};
officeCoreConfig.getCleanStyleMap().forEach((tagName, styles) -> {
if (StringUtils.isBlank((CharSequence)tagName) || CollectionUtils.isEmpty((Collection)styles)) {
return;
}
styles.forEach(style -> {
if (StringUtils.isBlank((CharSequence)style)) {
return;
}
if (tagName.equals(el.tagName())) {
originalStyle[0] = originalStyle[0].replaceAll((String)style, "");
}
});
if (StringUtils.isBlank((CharSequence)originalStyle[0])) {
el.removeAttr(AttrEnum.STYLE.getAttr());
return;
}
String newStyle = Arrays.stream(originalStyle[0].split(";")).filter(StringUtils::isNotBlank).map(e -> e.trim() + "; ").collect(Collectors.joining()).trim();
el.attr(AttrEnum.STYLE.getAttr(), newStyle);
});
}
private static void dealSubSup(org.jsoup.nodes.Document doc) {
try {
Elements elements = doc.select("span[style~=(?:vertical-align: (sub|super);font-size: smaller;)]");
for (Element span : elements) {
List<TagStyleBO> styles = TagEnum.getStyleList(span);
boolean isSub = styles.stream().anyMatch(e -> AttrEnum.VERTICAL_ALIGN.getAttr().equals(e.getAttr()) && TagEnum.SUB.getName().equals(e.getValue()));
Element suElement = new Element(isSub ? TagEnum.SUB.getName() : TagEnum.SUP.getName()).html(span.html());
if (suElement.childNodeSize() == 0) {
span.remove();
continue;
}
span.html(suElement.outerHtml());
String styleValue = styles.stream().filter(e -> !AttrEnum.VERTICAL_ALIGN.getAttr().equals(e.getAttr()) && !AttrEnum.FONT_SIZE.getAttr().equals(e.getAttr())).map(e -> e.getAttr() + ": " + e.getValue()).collect(Collectors.joining(";"));
if (StringUtils.isBlank((CharSequence)styleValue)) {
span.removeAttr(AttrEnum.STYLE.getAttr());
continue;
}
span.attr(AttrEnum.STYLE.getAttr(), styleValue);
}
}
catch (Exception e2) {
log.error("\u5904\u7406\u4e0a\u6807\u3001\u4e0b\u6807\u5f02\u5e38", (Throwable)e2);
}
}
private static void dealImg(ParseBO parseBO, org.jsoup.nodes.Document doc) {
try {
Elements elements = doc.select("img[src]");
if (MapUtils.isNotEmpty(parseBO.getImgMap())) {
for (Element img : elements) {
String src = img.attr(AttrEnum.SRC.getAttr());
String srcUrl = parseBO.getImgMap().get(src);
if (StringUtils.isNotBlank((CharSequence)srcUrl)) {
img.attr(AttrEnum.SRC.getAttr(), srcUrl);
}
WordParseUtil.adjustWidthHeight(img);
WordParseUtil.addImgAttr(img);
}
}
Elements elementImgNot = doc.select("img:not([src])");
elementImgNot.remove();
}
catch (Exception e) {
log.error("\u5904\u7406\u56fe\u7247\u5f02\u5e38", (Throwable)e);
}
}
private static void adjustWidthHeight(Element img) {
try {
String heightStr;
String widthStr;
String style = img.attr("style");
if (style != null && !style.isEmpty()) {
String widthValue = WordParseUtil.extractDimensionFromStyle(style, "width");
String heightValue = WordParseUtil.extractDimensionFromStyle(style, "height");
String newStyle = "";
if (widthValue != null) {
String widthPx = WordParseUtil.convertToPx(widthValue);
if (widthPx != null) {
img.attr("width", widthPx.replaceAll("[^0-9.]", ""));
}
newStyle = WordParseUtil.removeDimensionFromStyle(style, "width");
}
if (heightValue != null) {
String heightPx = WordParseUtil.convertToPx(heightValue);
if (heightPx != null) {
img.attr("height", heightPx.replaceAll("[^0-9.]", ""));
}
newStyle = WordParseUtil.removeDimensionFromStyle(newStyle, "height");
}
if (StringUtils.isBlank((CharSequence)newStyle)) {
img.removeAttr("style");
} else {
img.attr("style", newStyle);
}
}
if (StringUtils.isNotBlank((CharSequence)(widthStr = img.attr(AttrEnum.WIDTH.getAttr())))) {
double width = Double.parseDouble(Objects.requireNonNull(WordParseUtil.convertToPx(widthStr)));
img.attr(AttrEnum.WIDTH.getAttr(), Double.toString((double)Math.round((width /= officeCoreConfig.getImageScalingFactor().doubleValue()) * 100.0) / 100.0));
}
if (StringUtils.isNotBlank((CharSequence)(heightStr = img.attr(AttrEnum.HEIGHT.getAttr())))) {
double height = Double.parseDouble(Objects.requireNonNull(WordParseUtil.convertToPx(heightStr)));
img.attr(AttrEnum.HEIGHT.getAttr(), Double.toString((double)Math.round((height /= officeCoreConfig.getImageScalingFactor().doubleValue()) * 100.0) / 100.0));
}
}
catch (Exception e) {
log.error("\u8c03\u6574\u5bbd\u9ad8\u5f02\u5e38", (Throwable)e);
}
}
private static String convertToPx(String value) {
if (StringUtils.isBlank((CharSequence)value)) {
return null;
}
value = value.trim().toLowerCase();
Pattern pattern = Pattern.compile("([0-9.]+)\\s*([a-z%]*)");
Matcher matcher = pattern.matcher(value);
if (matcher.matches()) {
String unit;
double numericValue = Double.parseDouble(matcher.group(1));
switch (unit = matcher.group(2)) {
case "pt": {
return String.valueOf(Math.round(numericValue * 4.0 / 3.0));
}
case "in": {
return String.valueOf(Math.round(numericValue * 96.0));
}
case "cm": {
return String.valueOf(Math.round(numericValue * 96.0 / 2.54));
}
case "mm": {
return String.valueOf(Math.round(numericValue * 96.0 / 25.4));
}
case "": {
return String.valueOf(Math.round(numericValue));
}
}
return String.valueOf(Math.round(numericValue));
}
return null;
}
private static String extractDimensionFromStyle(String style, String dimension) {
String value;
if (StringUtils.isBlank((CharSequence)style) || StringUtils.isBlank((CharSequence)dimension)) {
return null;
}
Pattern pattern = Pattern.compile(dimension + "\\s*:\\s*([^;]+)(?:;|$)");
Matcher matcher = pattern.matcher(style);
if (matcher.find() && WordParseUtil.isValidDimensionValue(value = matcher.group(1).trim())) {
return value;
}
return null;
}
private static boolean isValidDimensionValue(String value) {
if (StringUtils.isBlank((CharSequence)value)) {
return false;
}
Pattern pattern = Pattern.compile("^[0-9]+(\\.[0-9]+)?\\s*(px|pt|in|cm|mm|%|em|rem|ex|ch|vw|vh|vmin|vmax)?$");
return pattern.matcher(value).matches();
}
private static String removeDimensionFromStyle(String style, String dimension) {
if (StringUtils.isBlank((CharSequence)style) || StringUtils.isBlank((CharSequence)dimension)) {
return style;
}
Pattern pattern = Pattern.compile(dimension + "\\s*:\\s*[^;]+;?");
Matcher matcher = pattern.matcher(style);
String result = matcher.replaceAll("");
result = result.replaceAll(";;", ";").replaceAll("^;|;$", "");
return result;
}
private static void dealLi(org.jsoup.nodes.Document doc) {
try {
Elements elements = doc.getElementsByTag(TagEnum.LI.getName());
for (Element li : elements) {
String style = li.attr(AttrEnum.STYLE.getAttr()) + "line-height: 2;";
li.tagName(TagEnum.P.getName()).attr(AttrEnum.STYLE.getAttr(), style);
}
}
catch (Exception e) {
log.error("\u5904\u7406\u5217\u8868\u5f02\u5e38", (Throwable)e);
}
}
private static void dealBookTitle(org.jsoup.nodes.Document doc) {
try {
Elements elements = doc.select(":matchesOwn(\u300a|\u300b)");
for (int i = 0; i < elements.size(); ++i) {
Node node;
int j;
Element end;
Element start = (Element)elements.get(i);
if (!start.text().contains("\u300a") || i + 1 >= elements.size() || !(end = (Element)elements.get(i + 1)).text().contains("\u300b")) continue;
if (Objects.nonNull(start.parent()) && start.parent().equals((Object)end.parent())) {
List siblings = start.parent().childNodes();
int startIndex = siblings.indexOf(start);
int endIndex = siblings.indexOf(end);
if (startIndex == -1 || endIndex == -1 || startIndex > endIndex) continue;
StringBuilder content = new StringBuilder();
ArrayList<Node> deleteList = new ArrayList<Node>();
for (j = startIndex; j <= endIndex; ++j) {
node = (Node)siblings.get(j);
if (node instanceof TextNode) {
content.append(((TextNode)node).getWholeText());
} else if (node instanceof Element) {
content.append(((Element)node).text());
}
if (j <= startIndex) continue;
deleteList.add(node);
}
start.text(content.toString());
deleteList.forEach(Node::remove);
continue;
}
if (!Objects.nonNull(start.parent()) || !Objects.nonNull(start.parent().parent()) || !start.parent().parent().equals((Object)end.parent()) || start.parent().siblingIndex() >= end.siblingIndex()) continue;
StringBuilder content = new StringBuilder();
ArrayList<Node> deleteList = new ArrayList<Node>();
Element startParent = start.parent();
List parentChild = startParent.childNodes();
int startIndex = parentChild.indexOf(start);
if (startIndex != -1) {
for (j = startIndex + 1; j < parentChild.size(); ++j) {
node = (Node)parentChild.get(j);
if (node instanceof TextNode) {
content.append(((TextNode)node).getWholeText());
} else if (node instanceof Element) {
content.append(((Element)node).text());
}
deleteList.add(node);
}
}
Element grandParent = start.parent().parent();
List grandSiblings = grandParent.childNodes();
int parentIdx = grandSiblings.indexOf(startParent);
int endIdx = grandSiblings.indexOf(end);
if (parentIdx != -1 && endIdx != -1 && parentIdx < endIdx) {
for (int j2 = parentIdx + 1; j2 <= endIdx; ++j2) {
Node node2 = (Node)grandSiblings.get(j2);
if (node2 instanceof TextNode) {
content.append(((TextNode)node2).getWholeText());
} else if (node2 instanceof Element) {
content.append(((Element)node2).text());
}
deleteList.add(node2);
}
}
start.text(content.toString());
deleteList.forEach(Node::remove);
}
}
catch (Exception e) {
log.error("\u5904\u7406\u4e66\u540d\u53f7\u5f02\u5e38", (Throwable)e);
}
}
private static void dealUnderline(org.jsoup.nodes.Document doc) {
try {
Elements elements = doc.select("span[style*='text-decoration: underline']");
for (Element u : elements) {
String style = u.attr("style");
if (!style.matches(".*text-decoration:\\s*underline\\s*(;|$).*")) continue;
u.tagName(TagEnum.U.getName());
WordParseUtil.processSpanContent((Node)u);
}
}
catch (Exception e) {
log.error("\u5904\u7406\u4e0b\u5212\u7ebf\u5f02\u5e38", (Throwable)e);
}
}
private static void dealCustomTextDecoration(org.jsoup.nodes.Document doc) {
try {
Elements elements = doc.select("span[style*='background-image: repeating-linear-gradient']");
for (Element span : elements) {
LinkedHashMap<String, TagStyleBO> styleMap = new LinkedHashMap<String, TagStyleBO>();
List<String> styles = Arrays.asList(span.attr("style").split(";"));
styles.forEach(style -> {
if (StringUtils.isBlank((CharSequence)style)) {
return;
}
String[] split = style.split(":");
if (split.length < 2) {
return;
}
TagStyleBO tagStyleBO = new TagStyleBO().setTagName(span.tagName()).setAttr(split[0].trim()).setValue(split[1].trim());
styleMap.put(tagStyleBO.getAttr(), tagStyleBO);
});
if (!styleMap.containsKey("background-size")) {
return;
}
span.addClass(((TagStyleBO)styleMap.get("background-size")).getValue().contains("11px") ? "custom-text-decoration-double-dot-dashed" : "custom-text-decoration-dot-dashed");
ArrayList newStyleList = new ArrayList();
styleMap.forEach((key, value) -> {
if (!Constants.DOT_DASHED_STYLE_SET.contains(key)) {
newStyleList.add(value.getAttr() + ": " + value.getValue() + ";");
}
});
if (CollectionUtils.isEmpty(newStyleList)) {
span.removeAttr(AttrEnum.STYLE.getAttr());
continue;
}
span.attr(AttrEnum.STYLE.getAttr(), String.join((CharSequence)" ", newStyleList));
}
}
catch (Exception e) {
log.error("\u5904\u7406\u81ea\u5b9a\u4e49\u6587\u672c\u88c5\u9970\uff08\u70b9\u5212\u7ebf\uff09\u5f02\u5e38", (Throwable)e);
}
}
private static void dealUnderlineAndLineThrough(org.jsoup.nodes.Document doc) {
try {
Elements elements = doc.select("span[style*='jby-line-through: true']");
for (int i = elements.size() - 1; i >= 0; --i) {
Element span = (Element)elements.get(i);
Element wrapper = new Element("span");
wrapper.attr("style", "text-decoration: line-through");
span.replaceWith((Node)wrapper);
wrapper.appendChild((Node)span);
}
}
catch (Exception e) {
log.error("\u5904\u7406\u4e0b\u5212\u7ebf\u548c\u5220\u9664\u5e76\u5b58\u5f02\u5e38", (Throwable)e);
}
}
private static String dealPlaceholder(ParseBO parseBO, org.jsoup.nodes.Document doc) {
String result = doc.html();
if (MapUtils.isNotEmpty(parseBO.getImageMap())) {
for (Map.Entry<String, ImageBO> entry : parseBO.getImageMap().entrySet()) {
String imgUrl = entry.getValue().getPictureUrl();
Element element = new Element(TagEnum.IMG.getName());
element.attr(AttrEnum.SRC.getAttr(), imgUrl);
element.attr(AttrEnum.WIDTH.getAttr(), String.valueOf(entry.getValue().getWidth().intValue()));
element.attr(AttrEnum.HEIGHT.getAttr(), String.valueOf(entry.getValue().getHeight().intValue()));
WordParseUtil.addImgAttr(element);
result = result.replace(entry.getKey(), element.outerHtml());
}
}
if (MapUtils.isNotEmpty(parseBO.getOpenOfficeXmlMap())) {
for (Map.Entry<String, Object> entry : parseBO.getOpenOfficeXmlMap().entrySet()) {
result = WordParseUtil.dealPlaceholder(parseBO, entry, result, false);
}
}
if (MapUtils.isNotEmpty(parseBO.getMathTypeMap())) {
for (Map.Entry<String, Object> entry : parseBO.getMathTypeMap().entrySet()) {
result = WordParseUtil.dealPlaceholder(parseBO, entry, result, false);
}
}
if (MapUtils.isNotEmpty(parseBO.getEqLatexMap())) {
for (Map.Entry<String, Object> entry : parseBO.getEqLatexMap().entrySet()) {
result = WordParseUtil.dealPlaceholder(parseBO, entry, result, true);
}
}
result = result.replaceAll("JBY_nbsp;", "&nbsp;");
result = result.replaceAll("font-style: italic;", "font-style: italic; z-index: 1;");
result = result.replaceAll("border-color: #auto;", "border-color: transparent;");
result = result.replaceAll("JBY_TEXTBOX_JBYBR", "<br/>");
result = result.replaceAll("JBY_TEXTBOX_JBY", "");
result = result.replaceAll(">\\s+(?=<(?!/span))", ">");
result = result.replaceAll("(background-color:\\s*#[0-9A-Fa-f]{3,6}[^;]*;)\\s*background-color:\\s*#[0-9A-Fa-f]{3,6}[^;]*;", "$1");
for (Iterator<Map.Entry<String, Object>> iterator : SYMBOL) {
Element imgElement = new Element(TagEnum.IMG.getName());
imgElement.attr(AttrEnum.SRC.getAttr(), "https://resource.xinjiaoyu.com/prod/office/unicode-symbol/" + ((String)((Object)iterator)).substring(2).toUpperCase() + ".svg");
imgElement.attr(AttrEnum.WIDTH.getAttr(), "14");
imgElement.attr(AttrEnum.HEIGHT.getAttr(), "14");
result = result.replace("@@@" + ((String)((Object)iterator)).substring(2).toUpperCase() + "@@@", imgElement.outerHtml());
result = result.replace("\ue225\ue226", "\\(\\rightleftharpoons\\)");
}
WordParseUtil.writeHtml(result);
return result;
}
private static String dealPlaceholder(ParseBO parseBO, Map.Entry<String, String> entry, String html, Boolean isEq) {
String value = entry.getValue();
if (isEq.booleanValue() || !Boolean.TRUE.equals(parseBO.getNewParseVersion())) {
value = WordParseUtil.latexReplace(parseBO.getLatexReplaceList(), value);
}
if (!value.startsWith("<img") && !entry.getKey().endsWith("JBYEQNUM")) {
value = "\\(" + value + "\\)";
}
html = html.replace(entry.getKey(), value);
log.info("latexReplace,\u66ff\u6362\u524d{},\u66ff\u6362\u540e{}", (Object)entry.getValue(), (Object)value);
return html;
}
private static String latexReplace(List<JSONObject> latexReplaceList, String latex) {
try {
if (StringUtils.isBlank((CharSequence)latex)) {
return latex;
}
if (CollectionUtils.isEmpty(latexReplaceList)) {
return latex;
}
if (latex.startsWith("<img")) {
return latex;
}
for (JSONObject latexReplace : latexReplaceList) {
String key = latexReplace.getString("key");
String value = latexReplace.getString("value");
if (StringUtils.isBlank((CharSequence)key) || StringUtils.isBlank((CharSequence)value)) continue;
latex = latex.replaceAll(key, value);
}
return WordParseUtil.wrapTextColorWithBraces(latex);
}
catch (Exception e) {
log.error("latex\u516c\u5f0f\u89c4\u8303\u6b63\u5219\u66ff\u6362\u5904\u7406\u5f02\u5e38:{}", (Object)latex, (Object)e);
return latex;
}
}
public static String wrapTextColorWithBraces(String input) {
if (input == null || input.isEmpty()) {
return input;
}
Pattern pattern = Pattern.compile("\\\\textcolor\\[rgb\\]\\{[^}]*\\}\\{");
ArrayList<int[]> matches = new ArrayList<int[]>();
Matcher matcher = pattern.matcher(input);
int start = 0;
while (matcher.find(start)) {
int contentStart = matcher.end() - 1;
int depth = 0;
for (int pos = contentStart; pos < input.length(); ++pos) {
char c = input.charAt(pos);
if (c == '{') {
++depth;
continue;
}
if (c != '}' || --depth != 0) continue;
matches.add(new int[]{matcher.start(), pos});
break;
}
start = matcher.start() + 1;
}
matches.sort(Comparator.comparingInt(a -> -a[0]));
StringBuilder sb = new StringBuilder(input);
for (int[] match : matches) {
int s = match[0];
int e = match[1];
sb.insert(e + 1, '}');
sb.insert(s, '{');
}
return sb.toString();
}
public static Element getMatchParent(Element element, String cssQuery) {
if (element == null) {
return null;
}
if (element.is(cssQuery)) {
return element;
}
return WordParseUtil.getMatchParent(element.parent(), cssQuery);
}
public static void addImgAttr(Element img) {
img.attr("data-default-src", img.attr(AttrEnum.SRC.getAttr()));
img.attr(AttrEnum.CLASS.getAttr(), "img-t");
img.attr("data-mce-resize", "false");
}
public static void checkSuffixAndSize(File file, Integer checkSize) {
WordParseUtil.validSuffix(file.getName());
WordParseUtil.validSize(file.length(), checkSize);
}
public static void checkSuffixAndSize(MultipartFile file, Integer checkSize) {
WordParseUtil.validSuffix(file.getOriginalFilename());
WordParseUtil.validSize(file.getSize(), checkSize);
}
private static void validSuffix(String filename) {
if (StringUtils.isBlank((CharSequence)filename)) {
throw new BusinessException("\u6587\u4ef6\u683c\u5f0f\u5f02\u5e38\uff01");
}
String suffix = com.jby.common.util.FileUtil.getFileSuffix((String)filename);
BizAssert.isTrue(("docx".equalsIgnoreCase(suffix) || "wps".equalsIgnoreCase(suffix) ? 1 : 0) != 0, (String)"\u4ec5\u652f\u6301docx\u683c\u5f0f\u548cwps\u6587\u6863\u89e3\u6790\uff01");
}
public static void validSize(double fileSize, Integer checkSize) {
if (checkSize == null || checkSize <= 0) {
checkSize = officeCoreConfig.getCheckSize();
}
BizAssert.isTrue(((fileSize /= 1048576.0) <= (double)checkSize.intValue() ? 1 : 0) != 0, (String)"\u6587\u4ef6\u5927\u5c0f\u8d85\u51fa\u9650\u5b9a\u503c\uff01");
}
private static void createTempDir(ParseBO parseBO) {
try {
Path tempDir = Files.createTempDirectory(Paths.get(officeCoreConfig.getTmpPath(), new String[0]), "parse-", new FileAttribute[0]);
parseBO.setTempDir(tempDir);
parseBO.setImagesDir(tempDir.resolve("images").toString());
parseBO.setHtmlPath(tempDir.resolve("output.html").toString());
parseBO.setOssFolder(tempDir.getFileName().toString());
}
catch (IOException e) {
log.error("\u521b\u5efa\u4e34\u65f6\u6587\u4ef6\u5939\u5f02\u5e38");
}
}
private static void writeHtml(String html) {
if (!"local".equals(SpringContextHolder.getActiveProfile())) {
return;
}
String savePath = officeCoreConfig.getTmpPath() + "/upload" + File.separator + UniqueUtil.getUuid() + "." + "html";
File file = OfficeFileUtil.writeFile(html, savePath);
log.info("==========================================\u672c\u5730html\u6587\u4ef6\u8def\u5f84\uff1a{}", (Object)file.getPath());
}
private static void handleFormat(ParseBO parseBO) {
String tempDir = parseBO.getTempDir() + "/temp";
try {
WordParseUtil.unzipDocx(parseBO.getSourceFilePath(), tempDir);
String content = "";
Path path = Paths.get(tempDir + "/word/document.xml", new String[0]);
try (BufferedReader reader = Files.newBufferedReader(path, StandardCharsets.UTF_8);){
content = reader.lines().collect(Collectors.joining(System.lineSeparator()));
if (content.contains("<w:b w:val=\"off\"")) {
content = content.replace("<w:b w:val=\"off\"", "<w:b w:val=\"0\"");
}
if (content.contains("<w:i w:val=\"off\"")) {
content = content.replace("<w:i w:val=\"off\"", "<w:i w:val=\"0\"");
}
content = content.replaceAll("[\\u200B\\u200C\\u200D]", "");
content = content.replaceAll("\\u00A0", " ");
content = content.replaceAll("\\uf028", "(");
content = content.replaceAll("\\uf029", ")");
for (String sl : SYMBOL) {
content = content.replaceAll(sl, "@@@" + sl.substring(2).toUpperCase() + "@@@");
}
content = content.replace("<w:shd w:val=\"pct15\" w:color=\"auto\" w:fill=\"FFFFFF\"/>", "<w:shd w:val=\"clear\" w:color=\"FFFFFF\" w:fill=\"D9D9D9\"/>");
content = content.replace("<w:shd w:val=\"pct10\" w:color=\"auto\" w:fill=\"FFFFFF\"/>", "<w:shd w:val=\"clear\" w:color=\"FFFFFF\" w:fill=\"E5E5E5\"/>");
}
catch (IOException e) {
log.error("\u5904\u7406\u6e90\u6587\u4ef6\u683c\u5f0f\u5f02\u5e38\uff1a{}", (Object)e.getMessage(), (Object)e);
}
Files.write(path, content.getBytes(StandardCharsets.UTF_8), new OpenOption[0]);
WordParseUtil.zipToDocx(tempDir, parseBO.getSourceFilePath());
}
catch (Exception e) {
log.error("\u5904\u7406\u6e90\u6587\u4ef6\u683c\u5f0f\u5f02\u5e38\uff1a{}", (Object)e.getMessage(), (Object)e);
}
}
private static void unzipDocx(String docxPath, String outputDir) throws IOException {
File dir = new File(outputDir);
if (!dir.exists()) {
dir.mkdirs();
}
try (ZipFile zipFile = new ZipFile(docxPath);){
Enumeration<? extends ZipEntry> entries = zipFile.entries();
while (entries.hasMoreElements()) {
ZipEntry entry = entries.nextElement();
File entryFile = new File(outputDir, entry.getName());
if (entry.isDirectory()) {
entryFile.mkdirs();
continue;
}
entryFile.getParentFile().mkdirs();
InputStream is = zipFile.getInputStream(entry);
Throwable throwable = null;
try {
FileOutputStream fos = new FileOutputStream(entryFile);
Throwable throwable2 = null;
try {
int len;
byte[] buffer = new byte[1024];
while ((len = is.read(buffer)) > 0) {
fos.write(buffer, 0, len);
}
}
catch (Throwable throwable3) {
throwable2 = throwable3;
throw throwable3;
}
finally {
if (fos == null) continue;
if (throwable2 != null) {
try {
fos.close();
}
catch (Throwable throwable4) {
throwable2.addSuppressed(throwable4);
}
continue;
}
fos.close();
}
}
catch (Throwable throwable5) {
throwable = throwable5;
throw throwable5;
}
finally {
if (is == null) continue;
if (throwable != null) {
try {
is.close();
}
catch (Throwable throwable6) {
throwable.addSuppressed(throwable6);
}
continue;
}
is.close();
}
}
}
}
private static void zipToDocx(String sourceDir, String outputDocx) throws IOException {
try (FileOutputStream fos = new FileOutputStream(outputDocx);
ZipOutputStream zos = new ZipOutputStream(fos);){
File rootDir = new File(sourceDir);
WordParseUtil.addFolderToZip(rootDir, rootDir, zos);
}
}
private static void addFolderToZip(File rootDir, File folder, ZipOutputStream zos) throws IOException {
for (File file : Objects.requireNonNull(folder.listFiles())) {
if (file.isDirectory()) {
WordParseUtil.addFolderToZip(rootDir, file, zos);
continue;
}
String entryName = rootDir.toPath().relativize(file.toPath()).toString().replace(File.separator, "/");
ZipEntry zipEntry = new ZipEntry(entryName);
zos.putNextEntry(zipEntry);
try (FileInputStream fis = new FileInputStream(file);){
int len;
byte[] buffer = new byte[1024];
while ((len = fis.read(buffer)) > 0) {
zos.write(buffer, 0, len);
}
}
zos.closeEntry();
}
}
private static String getFileParseResult(ParseBO parseBO, String md5) {
try {
OfficeFileParseRecordVO officeFileParseRecord = (OfficeFileParseRecordVO)FeignUtils.parse((Result)fileServiceFeign.getOfficeFileParseRecordByMd5(md5));
if (Objects.nonNull(officeFileParseRecord)) {
log.info("\u6587\u4ef6\u5df2\u88ab\u89e3\u6790\u8fc7,MD5: {}", (Object)md5);
OfficeFileParseRecordParam officeFileParseRecordParam = new OfficeFileParseRecordParam().setFileUrl(officeFileParseRecord.getFileUrl()).setFileMd5(officeFileParseRecord.getFileMd5()).setFileParseUrl(officeFileParseRecord.getFileParseUrl()).setFileId(parseBO.getFileId());
FeignUtils.parse((Result)fileServiceFeign.saveOfficeFileParseRecord(officeFileParseRecordParam));
return HttpClientUtil.doGet((String)com.jby.common.util.FileUtil.encodeUrl((String)officeFileParseRecord.getFileParseUrl()));
}
}
catch (Exception e) {
log.error("\u83b7\u53d6\u5386\u53f2\u89e3\u6790\u7ed3\u679c\u5f02\u5e38, md5: {}", (Object)md5, (Object)e);
}
return null;
}
private static void saveParseResult(ParseBO parseBO, String html) {
try {
String sourceFilePath = parseBO.getSourceFilePath();
String sourceFileBakPath = parseBO.getSourceFileBakPath();
if (StringUtils.isBlank((CharSequence)parseBO.getSourceFileUrl()) && StringUtils.isNotBlank((CharSequence)sourceFileBakPath)) {
File bakFile = new File(sourceFileBakPath);
String fileName = StringUtils.removeEnd((String)bakFile.getName(), (String)".JBY_BAK");
parseBO.setSourceFileUrl(WordParseUtil.uploadFileToOss(bakFile, "office/file/parse", parseBO.getOssFolder(), fileName));
}
String resultFilePath = sourceFilePath.substring(0, sourceFilePath.lastIndexOf(46)) + ".html";
File resultFile = OfficeFileUtil.writeFile(html, resultFilePath);
String fileParseUrl = WordParseUtil.uploadFileToOss(resultFile, "office/file/parse", parseBO.getOssFolder(), resultFile.getName());
if (StringUtils.isNotBlank((CharSequence)parseBO.getSourceFileUrl()) && StringUtils.isNotBlank((CharSequence)parseBO.getSourceFileMd5()) && StringUtils.isNotBlank((CharSequence)fileParseUrl)) {
OfficeFileParseRecordParam param = new OfficeFileParseRecordParam();
param.setFileUrl(parseBO.getSourceFileUrl());
param.setFileMd5(parseBO.getSourceFileMd5());
param.setFileParseUrl(fileParseUrl);
param.setFileId(parseBO.getFileId());
FeignUtils.parse((Result)fileServiceFeign.saveOfficeFileParseRecord(param));
}
}
catch (Exception e) {
log.error("\u4e0a\u4f20oss\u6216\u4fdd\u5b58\u89e3\u6790\u8bb0\u5f55\u5f02\u5e38", (Throwable)e);
}
}
private static void dealImg(ParseBO parseBO) {
HashMap<String, String> imgMap = new HashMap<String, String>();
HashMap urlToUuidMap = new HashMap();
HashMap keyToImgMap = new HashMap();
parseBO.getImageMap().forEach((key, value) -> {
if (value != null && value.getPictureUrl() != null) {
String url = value.getPictureUrl();
String uuid = urlToUuidMap.computeIfAbsent(url, k -> UniqueUtil.getUuid());
imgMap.put(uuid, url);
keyToImgMap.put(key, uuid);
}
});
ArrayList futuresOss = new ArrayList();
imgMap.forEach((key, value) -> {
CompletionStage future = CompletableFuture.runAsync(() -> {
try {
String imgUrl;
String fullPath = parseBO.getTempDir() + "/temp" + value;
String fileName = fullPath.substring(fullPath.lastIndexOf("/") + 1);
String fileSuffix = com.jby.common.util.FileUtil.getFileSuffix((String)fullPath).toLowerCase();
if ("tif".equals(fileSuffix) || "tiff".equals(fileSuffix)) {
WordParseUtil.tifToPng(new File(fullPath));
fullPath = fullPath.replaceAll("(?i)" + Pattern.quote(fileSuffix) + "$", "png");
fileName = fileName.replaceAll("(?i)" + Pattern.quote(fileSuffix) + "$", "png");
imgUrl = OssServiceUtil.uploadStream(new OssParam().setModule(AttachmentModuleEnum.OFFICE_IMG.getModule()).setFolder(parseBO.getOssFolder()).setInputStream(Files.newInputStream(Paths.get(fullPath, new String[0]), new OpenOption[0])).setFileName(fileName));
} else {
imgUrl = "wmf".equals(fileSuffix) || "emf".equals(fileSuffix) ? OfficeFileUtil.mf2svg(new ByteArrayInputStream(FileUtil.readBytes((String)fullPath)), fullPath) : OssServiceUtil.uploadStream(new OssParam().setModule(AttachmentModuleEnum.OFFICE_IMG.getModule()).setFolder(parseBO.getOssFolder()).setInputStream(Files.newInputStream(Paths.get(fullPath, new String[0]), new OpenOption[0])).setFileName(fileName));
}
imgMap.put((String)key, StringUtils.isNotBlank((CharSequence)imgUrl) ? imgUrl : fullPath);
}
catch (IOException e) {
log.error("\u5904\u7406\u56fe\u7247\u5931\u8d25, key: {}, value: {}", new Object[]{key, value, e});
}
}, WordParseUtil.getBatchDealPicExecutor()).exceptionally(throwable -> {
log.error("\u5904\u7406\u56fe\u7247\u5f02\u5e38", throwable);
return null;
});
futuresOss.add(future);
});
if (CollectionUtils.isNotEmpty(futuresOss)) {
try {
CompletableFuture.allOf(futuresOss.toArray(new CompletableFuture[0])).get(5L, TimeUnit.MINUTES);
log.info("\u56fe\u7247\u5904\u7406\u5b8c\u6210");
}
catch (TimeoutException e) {
log.error("\u56fe\u7247\u5904\u7406\u8d85\u65f6", (Throwable)e);
}
catch (InterruptedException e) {
log.error("\u56fe\u7247\u5904\u7406\u88ab\u4e2d\u65ad", (Throwable)e);
Thread.currentThread().interrupt();
}
catch (ExecutionException e) {
log.error("\u56fe\u7247\u5904\u7406\u5f02\u5e38", e.getCause());
}
}
parseBO.getImageMap().forEach((key, value) -> value.setPictureUrl((String)imgMap.get(keyToImgMap.get(key))));
}
public static String formatAsMillis(StopWatch sw) {
StringBuilder sb = new StringBuilder();
sb.append(sw.getId()).append("\n");
sb.append("---------------------------------------------\n");
sb.append(String.format("%-10s %-6s %s%n", "ms", "%", "Task name"));
sb.append("---------------------------------------------\n");
long totalMillis = Math.max(1L, sw.getTotalTimeMillis());
for (StopWatch.TaskInfo task : sw.getTaskInfo()) {
long ms = task.getTimeMillis();
int pct = (int)Math.round(100.0 * (double)ms / (double)totalMillis);
sb.append(String.format("%-10d %-6s %s%n", ms, pct + "%", task.getTaskName()));
}
return sb.toString();
}
}