diff --git a/pom.xml b/pom.xml index 43d89a88..1841c289 100644 --- a/pom.xml +++ b/pom.xml @@ -24,7 +24,7 @@ 4.4.11 5.2.5 1.0.6 - 24.8 + 25.10 3.0.6 diff --git a/server/src/main/java/cn/keking/service/FileHandlerService.java b/server/src/main/java/cn/keking/service/FileHandlerService.java index 7c4625e6..54e60e65 100644 --- a/server/src/main/java/cn/keking/service/FileHandlerService.java +++ b/server/src/main/java/cn/keking/service/FileHandlerService.java @@ -4,32 +4,18 @@ import cn.keking.config.ConfigConstants; 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.*; import cn.keking.web.filter.BaseUrlFilter; -import com.aspose.cad.*; -import com.aspose.cad.fileformats.cad.CadDrawTypeMode; -import com.aspose.cad.fileformats.tiff.enums.TiffExpectedFormat; -import com.aspose.cad.imageoptions.*; -import org.apache.commons.lang3.exception.ExceptionUtils; -import org.apache.pdfbox.Loader; -import org.apache.pdfbox.pdmodel.PDDocument; -import org.apache.pdfbox.rendering.ImageType; -import org.apache.pdfbox.rendering.PDFRenderer; -import org.apache.pdfbox.tools.imageio.ImageIOUtil; -import org.apache.poi.EncryptedDocumentException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.DependsOn; import org.springframework.stereotype.Component; -import org.springframework.util.CollectionUtils; import org.springframework.util.ObjectUtils; import org.springframework.util.StringUtils; import jakarta.servlet.http.HttpServletRequest; -import java.awt.image.BufferedImage; + import java.io.*; import java.net.URLDecoder; import java.net.URLEncoder; @@ -38,7 +24,6 @@ import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Objects; -import java.util.concurrent.*; import java.util.stream.IntStream; /** @@ -47,10 +32,10 @@ import java.util.stream.IntStream; */ @Component @DependsOn(ConfigConstants.BEAN_NAME) -public class FileHandlerService implements InitializingBean { +public class FileHandlerService { private static final String PDF2JPG_IMAGE_FORMAT = ".jpg"; - private static final String PDF_PASSWORD_MSG = "password"; + private final Logger logger = LoggerFactory.getLogger(FileHandlerService.class); private final String fileDir = ConfigConstants.getFileDir(); private final CacheService cacheService; @@ -144,15 +129,6 @@ public class FileHandlerService implements InitializingBean { cacheService.putImgCache(fileKey, imgs); } - /** - * cad定义线程池 - */ - private ExecutorService pool = null; - - @Override - public void afterPropertiesSet() throws Exception { - pool = Executors.newFixedThreadPool(ConfigConstants.getCadThread()); - } /** * 对转换后的文件进行操作(改变编码方式) @@ -192,7 +168,7 @@ public class FileHandlerService implements InitializingBean { * @param index 图片索引 * @return 图片访问地址 */ - private String getPdf2jpgUrl(String pdfFilePath, int index) { + public String getPdf2jpgUrl(String pdfFilePath, int index) { String baseUrl = BaseUrlFilter.getBaseUrl(); pdfFilePath = pdfFilePath.replace(fileDir, ""); String pdfFolder = pdfFilePath.substring(0, pdfFilePath.length() - 4); @@ -214,230 +190,20 @@ public class FileHandlerService implements InitializingBean { * @param pdfFilePath pdf文件路径 * @return 图片访问集合 */ - private List loadPdf2jpgCache(String pdfFilePath) { + public List loadPdf2jpgCache(String pdfFilePath) { // 移除 static 修饰符 List imageUrls = new ArrayList<>(); - Integer imageCount = this.getPdf2jpgCache(pdfFilePath); + Integer imageCount = this.getPdf2jpgCache(pdfFilePath); // 使用 this. 调用 if (Objects.isNull(imageCount)) { return imageUrls; } IntStream.range(0, imageCount).forEach(i -> { - String imageUrl = this.getPdf2jpgUrl(pdfFilePath, i); + String imageUrl = this.getPdf2jpgUrl(pdfFilePath, i); // 使用 this. 调用 imageUrls.add(imageUrl); }); return imageUrls; } - /** - * pdf文件转换成jpg图片集 - * fileNameFilePath pdf文件路径 - * pdfFilePath pdf输出文件路径 - * pdfName pdf文件名称 - * loadPdf2jpgCache 图片访问集合 - */ - public List pdf2jpg(String fileNameFilePath, String pdfFilePath, String pdfName, FileAttribute fileAttribute) throws Exception { - boolean forceUpdatedCache = fileAttribute.forceUpdatedCache(); - boolean usePasswordCache = fileAttribute.getUsePasswordCache(); - String filePassword = fileAttribute.getFilePassword(); - PDDocument doc; - final String[] pdfPassword = {null}; - final int[] pageCount = new int[1]; - if (!forceUpdatedCache) { - List cacheResult = this.loadPdf2jpgCache(pdfFilePath); - if (!CollectionUtils.isEmpty(cacheResult)) { - return cacheResult; - } - } - List imageUrls = new ArrayList<>(); - File pdfFile = new File(fileNameFilePath); - if (!pdfFile.exists()) { - return null; - } - int index = pdfFilePath.lastIndexOf("."); - String folder = pdfFilePath.substring(0, index); - File path = new File(folder); - if (!path.exists() && !path.mkdirs()) { - logger.error("创建转换文件【{}】目录失败,请检查目录权限!", folder); - } - try { - doc = Loader.loadPDF(pdfFile, filePassword); - doc.setResourceCache(new NotResourceCache()); - pageCount[0] = doc.getNumberOfPages(); - } catch (IOException e) { - Throwable[] throwableArray = ExceptionUtils.getThrowables(e); - for (Throwable throwable : throwableArray) { - if (throwable instanceof IOException || throwable instanceof EncryptedDocumentException) { - if (e.getMessage().toLowerCase().contains(PDF_PASSWORD_MSG)) { - pdfPassword[0] = PDF_PASSWORD_MSG; //查询到该文件是密码文件 输出带密码的值 - } - } - } - if (!PDF_PASSWORD_MSG.equals(pdfPassword[0])) { //该文件异常 错误原因非密码原因输出错误 - logger.error("Convert pdf exception, pdfFilePath:{}", pdfFilePath, e); - } - throw new Exception(e); - } - Callable > call = () -> { - try { - String imageFilePath; - BufferedImage image = null; - PDFRenderer pdfRenderer = new PDFRenderer(doc); - pdfRenderer.setSubsamplingAllowed(true); - for (int pageIndex = 0; pageIndex < pageCount[0]; pageIndex++) { - imageFilePath = folder + File.separator + pageIndex + PDF2JPG_IMAGE_FORMAT; - image = pdfRenderer.renderImageWithDPI(pageIndex, ConfigConstants.getPdf2JpgDpi(), ImageType.RGB); - ImageIOUtil.writeImage(image, imageFilePath, ConfigConstants.getPdf2JpgDpi()); - String imageUrl = this.getPdf2jpgUrl(pdfFilePath, pageIndex); - imageUrls.add(imageUrl); - } - image.flush(); - } catch (IOException e) { - throw new Exception(e); - } finally { - doc.close(); - } - return imageUrls; - }; - Future> result = pool.submit(call); - int pdftimeout; - if(pageCount[0] <=50){ - pdftimeout = ConfigConstants.getPdfTimeout(); - }else if(pageCount[0] <=200){ - pdftimeout = ConfigConstants.getPdfTimeout80(); - }else { - pdftimeout = ConfigConstants.getPdfTimeout200(); - } - try { - result.get(pdftimeout, TimeUnit.SECONDS); - // 如果在超时时间内,没有数据返回:则抛出TimeoutException异常 - } catch (InterruptedException | ExecutionException e) { - throw new Exception(e); - } catch (TimeoutException e) { - throw new Exception("overtime"); - } finally { - //关闭 - doc.close(); - } - if (usePasswordCache || ObjectUtils.isEmpty(filePassword)) { //加密文件 判断是否启用缓存命令 - this.addPdf2jpgCache(pdfFilePath, pageCount[0]); - } - return imageUrls; - } - /** - * cad文件转pdf - * - * @param inputFilePath cad文件路径 - * @param outputFilePath pdf输出文件路径 - * @return 转换是否成功 - */ - public String cadToPdf(String inputFilePath, String outputFilePath, String cadPreviewType, FileAttribute fileAttribute) throws Exception { - final InterruptionTokenSource source = new InterruptionTokenSource();//CAD延时 - final SvgOptions SvgOptions = new SvgOptions(); - final PdfOptions pdfOptions = new PdfOptions(); - final TiffOptions TiffOptions = new TiffOptions(TiffExpectedFormat.TiffJpegRgb); - if (fileAttribute.isCompressFile()) { //判断 是压缩包的创建新的目录 - int index = outputFilePath.lastIndexOf("/"); //截取最后一个斜杠的前面的内容 - String folder = outputFilePath.substring(0, index); - File path = new File(folder); - //目录不存在 创建新的目录 - if (!path.exists()) { - path.mkdirs(); - } - } - File outputFile = new File(outputFilePath); - try { - LoadOptions opts = new LoadOptions(); - opts.setSpecifiedEncoding(CodePages.SimpChinese); - final Image cadImage = Image.load(inputFilePath, opts); - try { - RasterizationQuality rasterizationQuality = new RasterizationQuality(); - rasterizationQuality.setArc(RasterizationQualityValue.High); - rasterizationQuality.setHatch(RasterizationQualityValue.High); - rasterizationQuality.setText(RasterizationQualityValue.High); - rasterizationQuality.setOle(RasterizationQualityValue.High); - rasterizationQuality.setObjectsPrecision(RasterizationQualityValue.High); - rasterizationQuality.setTextThicknessNormalization(true); - CadRasterizationOptions cadRasterizationOptions = new CadRasterizationOptions(); - cadRasterizationOptions.setBackgroundColor(Color.getWhite()); - cadRasterizationOptions.setPageWidth(cadImage.getWidth()); - cadRasterizationOptions.setPageHeight(cadImage.getHeight()); - cadRasterizationOptions.setUnitType(cadImage.getUnitType()); - cadRasterizationOptions.setAutomaticLayoutsScaling(false); - cadRasterizationOptions.setNoScaling(false); - cadRasterizationOptions.setQuality(rasterizationQuality); - cadRasterizationOptions.setDrawType(CadDrawTypeMode.UseObjectColor); - cadRasterizationOptions.setExportAllLayoutContent(true); - cadRasterizationOptions.setVisibilityMode(VisibilityMode.AsScreen); - switch (cadPreviewType) { //新增格式方法 - case "svg": - SvgOptions.setVectorRasterizationOptions(cadRasterizationOptions); - SvgOptions.setInterruptionToken(source.getToken()); - break; - case "pdf": - pdfOptions.setVectorRasterizationOptions(cadRasterizationOptions); - pdfOptions.setInterruptionToken(source.getToken()); - break; - case "tif": - TiffOptions.setVectorRasterizationOptions(cadRasterizationOptions); - TiffOptions.setInterruptionToken(source.getToken()); - break; - } - Callable call = () -> { - try (OutputStream stream = new FileOutputStream(outputFile)) { - switch (cadPreviewType) { - case "svg": - cadImage.save(stream, SvgOptions); - break; - case "pdf": - cadImage.save(stream, pdfOptions); - break; - case "tif": - cadImage.save(stream, TiffOptions); - break; - } - } catch (IOException e) { - logger.error("CADFileNotFoundException,inputFilePath:{}", inputFilePath, e); - return null; - } finally { - cadImage.dispose(); - source.interrupt(); //结束任务 - source.dispose(); - } - return "true"; - }; - Future result = pool.submit(call); - try { - result.get(Long.parseLong(ConfigConstants.getCadTimeout()), TimeUnit.SECONDS); - // 如果在超时时间内,没有数据返回:则抛出TimeoutException异常 - } catch (InterruptedException e) { - logger.error("CAD转换文件异常:", e); - return null; - } catch (ExecutionException e) { - logger.error("CAD转换在尝试取得任务结果时出错:", e); - return null; - } catch (TimeoutException e) { - logger.error("CAD转换时间超时:", e); - return null; - } finally { - source.interrupt(); //结束任务 - source.dispose(); - cadImage.dispose(); - // pool.shutdownNow(); - } - } finally { - source.dispose(); - cadImage.dispose(); - } - } finally { - source.dispose(); - } - if(cadPreviewType.equals("svg")){ - System.out.println(" This is a new line."); - System.out.println(outputFilePath); - RemoveSvgAdSimple.removeSvgAdFromFile(outputFilePath); - } - return "true"; - } /** * @param str 原字符串(待截取原串) diff --git a/server/src/main/java/cn/keking/service/impl/CadFilePreviewImpl.java b/server/src/main/java/cn/keking/service/impl/CadFilePreviewImpl.java index 6f75fce7..36304da1 100644 --- a/server/src/main/java/cn/keking/service/impl/CadFilePreviewImpl.java +++ b/server/src/main/java/cn/keking/service/impl/CadFilePreviewImpl.java @@ -3,6 +3,7 @@ package cn.keking.service.impl; import cn.keking.config.ConfigConstants; import cn.keking.model.FileAttribute; import cn.keking.model.ReturnResponse; +import cn.keking.service.CadToPdfService; import cn.keking.service.FileHandlerService; import cn.keking.service.FilePreview; import cn.keking.utils.DownloadUtils; @@ -15,7 +16,6 @@ import org.springframework.stereotype.Service; import org.springframework.ui.Model; import org.springframework.util.StringUtils; -import static cn.keking.service.impl.OfficeFilePreviewImpl.getPreviewType; /** * @author chenjh @@ -29,11 +29,15 @@ public class CadFilePreviewImpl implements FilePreview { private static final String OFFICE_PREVIEW_TYPE_ALL_IMAGES = "allImages"; private final FileHandlerService fileHandlerService; + private final CadToPdfService cadtopdfservice; private final OtherFilePreviewImpl otherFilePreview; + private final OfficeFilePreviewImpl officefilepreviewimpl; - public CadFilePreviewImpl(FileHandlerService fileHandlerService, OtherFilePreviewImpl otherFilePreview) { + public CadFilePreviewImpl(FileHandlerService fileHandlerService, OtherFilePreviewImpl otherFilePreview, CadToPdfService cadtopdfservice,OfficeFilePreviewImpl officefilepreviewimpl ) { this.fileHandlerService = fileHandlerService; this.otherFilePreview = otherFilePreview; + this.cadtopdfservice = cadtopdfservice; + this.officefilepreviewimpl = officefilepreviewimpl; } @Override @@ -53,14 +57,14 @@ public class CadFilePreviewImpl implements FilePreview { return otherFilePreview.notSupportedFile(model, fileAttribute, response.getMsg()); } String filePath = response.getContent(); - String imageUrls = null; + boolean imageUrls = false; if (StringUtils.hasText(outFilePath)) { try { - imageUrls = fileHandlerService.cadToPdf(filePath, outFilePath, cadPreviewType, fileAttribute); + imageUrls = cadtopdfservice.cadToPdf(filePath, outFilePath, cadPreviewType, fileAttribute); } catch (Exception e) { logger.error("Failed to convert CAD file: {}", filePath, e); } - if (imageUrls == null) { + if (!imageUrls) { return otherFilePreview.notSupportedFile(model, fileAttribute, "CAD转换异常,请联系管理员"); } //是否保留CAD源文件 @@ -82,7 +86,7 @@ public class CadFilePreviewImpl implements FilePreview { return SVG_FILE_PREVIEW_PAGE; } if (baseUrl != null && (OFFICE_PREVIEW_TYPE_IMAGE.equals(officePreviewType) || OFFICE_PREVIEW_TYPE_ALL_IMAGES.equals(officePreviewType))) { - return getPreviewType(model, fileAttribute, officePreviewType, cacheName, outFilePath, fileHandlerService, OFFICE_PREVIEW_TYPE_IMAGE, otherFilePreview); + return officefilepreviewimpl.getPreviewType(model, fileAttribute, officePreviewType, cacheName, outFilePath, fileHandlerService, OFFICE_PREVIEW_TYPE_IMAGE, otherFilePreview); } model.addAttribute("pdfUrl", cacheName); return PDF_FILE_PREVIEW_PAGE; diff --git a/server/src/main/java/cn/keking/service/impl/OfficeFilePreviewImpl.java b/server/src/main/java/cn/keking/service/impl/OfficeFilePreviewImpl.java index f2e66e71..1f78b10d 100644 --- a/server/src/main/java/cn/keking/service/impl/OfficeFilePreviewImpl.java +++ b/server/src/main/java/cn/keking/service/impl/OfficeFilePreviewImpl.java @@ -6,6 +6,7 @@ import cn.keking.model.ReturnResponse; import cn.keking.service.FileHandlerService; import cn.keking.service.FilePreview; import cn.keking.service.OfficeToPdfService; +import cn.keking.service.PdfToJpgService; import cn.keking.utils.DownloadUtils; import cn.keking.utils.KkFileUtils; import cn.keking.utils.OfficeUtils; @@ -35,11 +36,13 @@ public class OfficeFilePreviewImpl implements FilePreview { private final FileHandlerService fileHandlerService; private final OfficeToPdfService officeToPdfService; private final OtherFilePreviewImpl otherFilePreview; + private final PdfToJpgService pdftojpgservice; - public OfficeFilePreviewImpl(FileHandlerService fileHandlerService, OfficeToPdfService officeToPdfService, OtherFilePreviewImpl otherFilePreview) { + public OfficeFilePreviewImpl(FileHandlerService fileHandlerService, OfficeToPdfService officeToPdfService, OtherFilePreviewImpl otherFilePreview, PdfToJpgService pdftojpgservice) { this.fileHandlerService = fileHandlerService; this.officeToPdfService = officeToPdfService; this.otherFilePreview = otherFilePreview; + this.pdftojpgservice = pdftojpgservice; } @Override @@ -115,12 +118,12 @@ public class OfficeFilePreviewImpl implements FilePreview { return isHtmlView ? EXEL_FILE_PREVIEW_PAGE : PDF_FILE_PREVIEW_PAGE; } - static String getPreviewType(Model model, FileAttribute fileAttribute, String officePreviewType, String pdfName, String outFilePath, FileHandlerService fileHandlerService, String officePreviewTypeImage, OtherFilePreviewImpl otherFilePreview) { + String getPreviewType(Model model, FileAttribute fileAttribute, String officePreviewType, String pdfName, String outFilePath, FileHandlerService fileHandlerService, String officePreviewTypeImage, OtherFilePreviewImpl otherFilePreview) { String suffix = fileAttribute.getSuffix(); boolean isPPT = suffix.equalsIgnoreCase("ppt") || suffix.equalsIgnoreCase("pptx"); List imageUrls = null; try { - imageUrls = fileHandlerService.pdf2jpg(outFilePath,outFilePath, pdfName, fileAttribute); + imageUrls = pdftojpgservice.pdf2jpg(outFilePath,outFilePath, pdfName, fileAttribute); } catch (Exception e) { Throwable[] throwableArray = ExceptionUtils.getThrowables(e); for (Throwable throwable : throwableArray) { diff --git a/server/src/main/java/cn/keking/service/impl/PdfFilePreviewImpl.java b/server/src/main/java/cn/keking/service/impl/PdfFilePreviewImpl.java index 9640c13b..ca8dd05e 100644 --- a/server/src/main/java/cn/keking/service/impl/PdfFilePreviewImpl.java +++ b/server/src/main/java/cn/keking/service/impl/PdfFilePreviewImpl.java @@ -5,6 +5,7 @@ import cn.keking.model.FileAttribute; import cn.keking.model.ReturnResponse; import cn.keking.service.FileHandlerService; import cn.keking.service.FilePreview; +import cn.keking.service.PdfToJpgService; import cn.keking.utils.DownloadUtils; import cn.keking.utils.WebUtils; import org.apache.commons.lang3.exception.ExceptionUtils; @@ -24,10 +25,12 @@ public class PdfFilePreviewImpl implements FilePreview { private final FileHandlerService fileHandlerService; private final OtherFilePreviewImpl otherFilePreview; + private final PdfToJpgService pdftojpgservice; private static final String PDF_PASSWORD_MSG = "password"; - public PdfFilePreviewImpl(FileHandlerService fileHandlerService, OtherFilePreviewImpl otherFilePreview) { + public PdfFilePreviewImpl(FileHandlerService fileHandlerService, OtherFilePreviewImpl otherFilePreview, PdfToJpgService pdftojpgservice) { this.fileHandlerService = fileHandlerService; this.otherFilePreview = otherFilePreview; + this.pdftojpgservice = pdftojpgservice; } @Override public String filePreviewHandle(String url, Model model, FileAttribute fileAttribute) { @@ -51,7 +54,7 @@ public class PdfFilePreviewImpl implements FilePreview { } List imageUrls; try { - imageUrls = fileHandlerService.pdf2jpg(originFilePath,outFilePath, pdfName, fileAttribute); + imageUrls = pdftojpgservice.pdf2jpg(originFilePath,outFilePath, pdfName, fileAttribute); } catch (Exception e) { Throwable[] throwableArray = ExceptionUtils.getThrowables(e); for (Throwable throwable : throwableArray) { diff --git a/server/src/main/java/cn/keking/utils/RemoveSvgAdSimple.java b/server/src/main/java/cn/keking/utils/RemoveSvgAdSimple.java index 303674ef..3f0ec261 100644 --- a/server/src/main/java/cn/keking/utils/RemoveSvgAdSimple.java +++ b/server/src/main/java/cn/keking/utils/RemoveSvgAdSimple.java @@ -4,74 +4,9 @@ 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的元素及其内容 - * @param svgContent SVG内容字符串 - * @return 清理后的SVG内容 - */ - public static String removeSvgAdPrecisely(String svgContent) { - // 使用非贪婪模式匹配包含transform的元素及其完整内容 - String preservePattern = "]*transform\\s*=\\s*\"[^\"]*\"[^>]*>.*?"; - - // 查找所有包含transform的元素 - Pattern pattern = Pattern.compile(preservePattern, Pattern.DOTALL); - Matcher matcher = pattern.matcher(svgContent); - - StringBuilder result = new StringBuilder(); - // 添加XML声明和SVG根元素 - if (svgContent.contains(""); - } - - // 找到SVG开始标签 - int svgStart = svgContent.indexOf("", svgStart) + 1; - - if (svgStart != -1) { - // 添加SVG开始标签 - result.append(svgContent.substring(svgStart, svgEnd)); - - // 收集所有包含transform的元素 - while (matcher.find()) { - result.append("\n").append(matcher.group()); - } - - // 添加SVG结束标签 - result.append("\n"); - } else { - // 如果没有找到SVG标签,返回空或原始内容 - return svgContent; - } - - return result.toString(); - } - - /** - * 简单暴力版本:直接删除特定广告内容 - * @param svgContent SVG内容字符串 - * @return 清理后的SVG内容 - */ - public static String removeSvgAdSimple(String svgContent) { - // 查找包含广告的元素(根据你的示例,广告通常包含stroke="#FFFFFF"等特征) - String adPattern1 = "\\s*]*stroke=\"#FFFFFF\"[^>]*>.*?\\s*]*fill=\"#FFFFFF\"[^>]*>.*?\\s*"; - String adPattern2 = "\\s*]*M0 0L[^>]*stroke=\"#FFFFFF\"[^>]*>.*?.*?"; - - String result = svgContent; - result = result.replaceAll(adPattern1, ""); - result = result.replaceAll(adPattern2, ""); - - // 也可以直接删除所有不含transform属性的顶级元素 - // 这个正则会删除不带transform的顶级,但保留嵌套的 - result = result.replaceAll("(?s)(?:(?!).)*?", ""); - - return result; - } /** * 更可靠的版本:使用DOM解析思路,但用正则实现 @@ -84,7 +19,7 @@ public class RemoveSvgAdSimple { // 找到XML声明 if (svgContent.contains("") + 2; - cleaned.append(svgContent.substring(0, xmlEnd)).append("\n"); + cleaned.append(svgContent, 0, xmlEnd).append("\n"); } // 找到SVG开始标签 @@ -92,7 +27,7 @@ public class RemoveSvgAdSimple { if (svgStart == -1) return svgContent; int svgEnd = svgContent.indexOf(">", svgStart) + 1; - cleaned.append(svgContent.substring(svgStart, svgEnd)).append("\n"); + cleaned.append(svgContent, svgStart, svgEnd).append("\n"); // 解析剩余内容 String remaining = svgContent.substring(svgEnd); @@ -133,7 +68,7 @@ public class RemoveSvgAdSimple { } if (gClose != -1) { - cleaned.append(remaining.substring(gStart, gClose)).append("\n"); + cleaned.append(remaining, gStart, gClose).append("\n"); pos = gClose; } else { pos = gTagEnd + 1; @@ -166,14 +101,14 @@ public class RemoveSvgAdSimple { 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); + String svgContent = Files.readString(sourcePath); // 清理SVG广告 String cleanedContent = removeSvgAdReliable(svgContent); // 写入目标文件 Path targetPath = Paths.get(targetFilePath); - Files.write(targetPath, cleanedContent.getBytes(StandardCharsets.UTF_8)); + Files.writeString(targetPath, cleanedContent); System.out.println("SVG广告清理完成!"); }