服务: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 默认密钥已清空
1792 lines
87 KiB
Java
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(" ", " ");
|
|
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;", " ");
|
|
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();
|
|
}
|
|
}
|
|
|