更新 3d解析组件 更新pdfjs解析组件

This commit is contained in:
高雄
2026-01-06 16:07:29 +08:00
parent 00a8e094db
commit ea35da6694
298 changed files with 294883 additions and 112775 deletions

View File

@@ -5,10 +5,7 @@ import cn.keking.model.FileAttribute;
import cn.keking.model.FileType;
import cn.keking.service.cache.CacheService;
import cn.keking.service.cache.NotResourceCache;
import cn.keking.utils.EncodingDetects;
import cn.keking.utils.KkFileUtils;
import cn.keking.utils.UrlEncoderUtils;
import cn.keking.utils.WebUtils;
import cn.keking.utils.*;
import cn.keking.web.filter.BaseUrlFilter;
import com.aspose.cad.*;
import com.aspose.cad.fileformats.cad.CadDrawTypeMode;
@@ -434,6 +431,11 @@ public class FileHandlerService implements InitializingBean {
} finally {
source.dispose();
}
if(cadPreviewType.equals("svg")){
System.out.println(" This is a new line.");
System.out.println(outputFilePath);
RemoveSvgAdSimple.removeSvgAdFromFile(outputFilePath);
}
return "true";
}

View File

@@ -46,8 +46,7 @@ public class FtpUtils {
// 获取文件输入流
String encodedFilePath = new String(
connectionInfo.remoteFilePath.getBytes(connectionInfo.controlEncoding),
StandardCharsets.ISO_8859_1
connectionInfo.remoteFilePath.getBytes(connectionInfo.controlEncoding), StandardCharsets.ISO_8859_1
);
// 方法1直接下载文件到本地
@@ -85,8 +84,7 @@ public class FtpUtils {
// 获取文件输入流
String encodedFilePath = new String(
connectionInfo.remoteFilePath.getBytes(connectionInfo.controlEncoding),
StandardCharsets.ISO_8859_1
connectionInfo.remoteFilePath.getBytes(connectionInfo.controlEncoding), StandardCharsets.ISO_8859_1
);
// 获取文件输入流

View File

@@ -0,0 +1,180 @@
package cn.keking.utils;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.charset.StandardCharsets;
import java.util.regex.Pattern;
import java.util.regex.Matcher;
public class RemoveSvgAdSimple {
/**
* 改进版本直接处理SVG内容保留包含transform的<g>元素及其内容
* @param svgContent SVG内容字符串
* @return 清理后的SVG内容
*/
public static String removeSvgAdPrecisely(String svgContent) {
// 使用非贪婪模式匹配包含transform的<g>元素及其完整内容
String preservePattern = "<g\\s+[^>]*transform\\s*=\\s*\"[^\"]*\"[^>]*>.*?</g>";
// 查找所有包含transform的<g>元素
Pattern pattern = Pattern.compile(preservePattern, Pattern.DOTALL);
Matcher matcher = pattern.matcher(svgContent);
StringBuilder result = new StringBuilder();
// 添加XML声明和SVG根元素
if (svgContent.contains("<?xml")) {
result.append("<?xml version=\"1.0\" standalone=\"no\"?>");
}
// 找到SVG开始标签
int svgStart = svgContent.indexOf("<svg");
int svgEnd = svgContent.indexOf(">", svgStart) + 1;
if (svgStart != -1) {
// 添加SVG开始标签
result.append(svgContent.substring(svgStart, svgEnd));
// 收集所有包含transform的<g>元素
while (matcher.find()) {
result.append("\n").append(matcher.group());
}
// 添加SVG结束标签
result.append("\n</svg>");
} else {
// 如果没有找到SVG标签返回空或原始内容
return svgContent;
}
return result.toString();
}
/**
* 简单暴力版本:直接删除特定广告内容
* @param svgContent SVG内容字符串
* @return 清理后的SVG内容
*/
public static String removeSvgAdSimple(String svgContent) {
// 查找包含广告的<g>元素根据你的示例广告通常包含stroke="#FFFFFF"等特征)
String adPattern1 = "<g>\\s*<path[^>]*stroke=\"#FFFFFF\"[^>]*>.*?</path>\\s*<path[^>]*fill=\"#FFFFFF\"[^>]*>.*?</path>\\s*</g>";
String adPattern2 = "<g>\\s*<path[^>]*M0 0L[^>]*stroke=\"#FFFFFF\"[^>]*>.*?</path>.*?</g>";
String result = svgContent;
result = result.replaceAll(adPattern1, "");
result = result.replaceAll(adPattern2, "");
// 也可以直接删除所有不含transform属性的顶级<g>元素
// 这个正则会删除不带transform的顶级<g>,但保留嵌套的<g>
result = result.replaceAll("(?s)<g>(?:(?!<g>).)*?</g>", "");
return result;
}
/**
* 更可靠的版本使用DOM解析思路但用正则实现
* @param svgContent SVG内容字符串
* @return 清理后的SVG内容
*/
public static String removeSvgAdReliable(String svgContent) {
StringBuilder cleaned = new StringBuilder();
// 找到XML声明
if (svgContent.contains("<?xml")) {
int xmlEnd = svgContent.indexOf("?>") + 2;
cleaned.append(svgContent.substring(0, xmlEnd)).append("\n");
}
// 找到SVG开始标签
int svgStart = svgContent.indexOf("<svg");
if (svgStart == -1) return svgContent;
int svgEnd = svgContent.indexOf(">", svgStart) + 1;
cleaned.append(svgContent.substring(svgStart, svgEnd)).append("\n");
// 解析剩余内容
String remaining = svgContent.substring(svgEnd);
int pos = 0;
while (pos < remaining.length()) {
// 查找下一个<g>标签
int gStart = remaining.indexOf("<g", pos);
if (gStart == -1) break;
// 检查这个<g>标签是否包含transform属性
int gTagEnd = remaining.indexOf(">", gStart);
String gTag = remaining.substring(gStart, gTagEnd + 1);
if (gTag.contains("transform")) {
// 找到对应的</g>标签
int depth = 1;
int searchPos = gTagEnd + 1;
int gClose = -1;
while (searchPos < remaining.length()) {
int nextOpen = remaining.indexOf("<g", searchPos);
int nextClose = remaining.indexOf("</g>", searchPos);
if (nextClose != -1 && (nextClose < nextOpen || nextOpen == -1)) {
depth--;
if (depth == 0) {
gClose = nextClose + 4; // 包括</g>的4个字符
break;
}
searchPos = nextClose + 4;
} else if (nextOpen != -1 && nextOpen < nextClose) {
depth++;
searchPos = nextOpen + 2;
} else {
break;
}
}
if (gClose != -1) {
cleaned.append(remaining.substring(gStart, gClose)).append("\n");
pos = gClose;
} else {
pos = gTagEnd + 1;
}
} else {
// 跳过这个<g>元素及其内容
pos = gTagEnd + 1;
}
}
cleaned.append("</svg>");
return cleaned.toString();
}
/**
* 从文件路径读取SVG内容清理广告然后替换原文件
* @param filePath SVG文件路径
* @throws IOException 文件读写异常
*/
public static void removeSvgAdFromFile(String filePath) throws IOException {
removeSvgAdFromFile(filePath, filePath);
}
/**
* 从文件路径读取SVG内容清理广告然后写入目标文件
* @param sourceFilePath 源SVG文件路径
* @param targetFilePath 目标SVG文件路径
* @throws IOException 文件读写异常
*/
public static void removeSvgAdFromFile(String sourceFilePath, String targetFilePath) throws IOException {
// 读取文件内容
Path sourcePath = Paths.get(sourceFilePath);
String svgContent = new String(Files.readAllBytes(sourcePath), StandardCharsets.UTF_8);
// 清理SVG广告
String cleanedContent = removeSvgAdReliable(svgContent);
// 写入目标文件
Path targetPath = Paths.get(targetFilePath);
Files.write(targetPath, cleanedContent.getBytes(StandardCharsets.UTF_8));
System.out.println("SVG广告清理完成");
}
}

View File

@@ -11,15 +11,11 @@ import cn.keking.utils.FtpUtils;
import cn.keking.utils.KkFileUtils;
import cn.keking.utils.SslUtils;
import cn.keking.utils.WebUtils;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.type.TypeFactory;
import fr.opensagres.xdocreport.core.io.IOUtils;
import org.apache.commons.codec.binary.Base64;
import org.apache.hc.client5.http.classic.HttpClient;
import org.apache.hc.client5.http.impl.DefaultRedirectStrategy;
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
import org.apache.hc.client5.http.impl.classic.HttpClientBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpMethod;
@@ -156,6 +152,7 @@ public class OnlinePreviewController {
public void getCorsFile(@RequestParam String urlPath,
@RequestParam(required = false) String key,
HttpServletResponse response,
@RequestParam(required = false) String encryption,
FileAttribute fileAttribute) throws Exception {
// 1. 验证接口是否开启
@@ -170,7 +167,7 @@ public class OnlinePreviewController {
}
URL url;
try {
urlPath = WebUtils.decodeUrl(urlPath, "base64");
urlPath = WebUtils.decodeUrl(urlPath, encryption);
url = WebUtils.normalizedURL(urlPath);
} catch (Exception ex) {
logger.error(String.format(BASE64_DECODE_ERROR_MSG, urlPath),ex);