From 071f6aafbc995082ee66c1a903d563f45a25212e Mon Sep 17 00:00:00 2001 From: wangzhiwei Date: Fri, 10 Apr 2026 17:31:20 +0800 Subject: [PATCH] =?UTF-8?q?feat(skills):=20=E4=BC=98=E5=8C=96=E6=96=87?= =?UTF-8?q?=E4=BB=B6=E5=86=85=E5=AE=B9=E8=AF=BB=E5=8F=96=E9=80=BB=E8=BE=91?= =?UTF-8?q?=E5=B9=B6=E6=94=AF=E6=8C=81=E5=A4=9A=E7=A7=8D=E6=96=87=E4=BB=B6?= =?UTF-8?q?=E6=A0=BC=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 添加 Base64 编码支持用于图片处理 - 区分文本文件和二进制文件,只读取文本文件内容 - 为图片格式的 Base64 字符串实现按行分割(每行80字符) - 扩展文件格式识别,支持 js、ts、html、css、xml、csv 等格式 - 添加图片格式支持(png、jpg、jpeg、gif、bmp、webp、svg、ico) - 增加 pdf、压缩包、音视频等二进制文件格式识别 - 实现二进制文件格式判断方法,避免读取非文本内容 --- .../service/impl/SkillGenServiceImpl.java | 73 +++++++++++++++++-- 1 file changed, 67 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/kexue/skills/service/impl/SkillGenServiceImpl.java b/src/main/java/com/kexue/skills/service/impl/SkillGenServiceImpl.java index ff1b06c..2dc3b6b 100644 --- a/src/main/java/com/kexue/skills/service/impl/SkillGenServiceImpl.java +++ b/src/main/java/com/kexue/skills/service/impl/SkillGenServiceImpl.java @@ -48,6 +48,7 @@ import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.ArrayList; import java.util.Arrays; +import java.util.Base64; import java.util.Date; import java.util.Enumeration; import java.util.HashMap; @@ -933,13 +934,24 @@ public class SkillGenServiceImpl implements SkillGenService { fileNode.setFormat(getFileFormat(fileName)); fileNode.setDescription(fileName + " 文件"); - // 读取文件内容 - try { - String content = new String(entry.getValue(), StandardCharsets.UTF_8); - fileNode.setContent(content); - } catch (Exception e) { - log.warn("读取文件内容失败: {}", filePath, e); + // 读取文件内容(仅文本文件,图片等二进制文件不读取内容) + String fileFormat = getFileFormat(fileName); + boolean isBinaryFile = isBinaryFormat(fileFormat); + + if (!isBinaryFile) { + // 文本文件,读取内容 + try { + String content = new String(entry.getValue(), StandardCharsets.UTF_8); + fileNode.setContent(content); + } catch (Exception e) { + log.warn("读取文件内容失败: {}", filePath, e); + fileNode.setContent(""); + } + } else { + // 二进制文件(如图片),不读取内容,仅记录文件大小信息 + int fileSize = entry.getValue().length; fileNode.setContent(""); + log.debug("二进制文件: {} ({} bytes)", fileName, fileSize); } // 添加到父节点 @@ -1159,6 +1171,21 @@ public class SkillGenServiceImpl implements SkillGenService { // 文件类型,添加content if (node.getContent() != null && !node.getContent().isEmpty()) { String rawContent = node.getContent(); + + // 如果是图片格式,Base64字符串需要按行分割(每行80字符) + if ("image".equals(node.getFormat())) { + int lineLength = 80; + StringBuilder base64Lines = new StringBuilder(); + for (int i = 0; i < rawContent.length(); i += lineLength) { + if (i > 0) { + base64Lines.append("\n"); + } + int end = Math.min(i + lineLength, rawContent.length()); + base64Lines.append(rawContent.substring(i, end)); + } + rawContent = base64Lines.toString(); + } + // 将Tab替换为4个空格(YAML不允许Tab) rawContent = rawContent.replace("\t", " "); @@ -1227,10 +1254,44 @@ public class SkillGenServiceImpl implements SkillGenService { return "json"; } else if (lowerName.endsWith(".yaml") || lowerName.endsWith(".yml")) { return "yaml"; + } else if (lowerName.endsWith(".js") || lowerName.endsWith(".ts")) { + return "javascript"; + } else if (lowerName.endsWith(".html")) { + return "html"; + } else if (lowerName.endsWith(".css")) { + return "css"; + } else if (lowerName.endsWith(".xml")) { + return "xml"; + } else if (lowerName.endsWith(".csv")) { + return "csv"; + } else if (lowerName.endsWith(".png") || lowerName.endsWith(".jpg") || lowerName.endsWith(".jpeg") || + lowerName.endsWith(".gif") || lowerName.endsWith(".bmp") || lowerName.endsWith(".webp") || + lowerName.endsWith(".svg") || lowerName.endsWith(".ico")) { + return "image"; + } else if (lowerName.endsWith(".pdf")) { + return "pdf"; + } else if (lowerName.endsWith(".zip") || lowerName.endsWith(".rar") || lowerName.endsWith(".7z")) { + return "archive"; + } else if (lowerName.endsWith(".mp4") || lowerName.endsWith(".avi") || lowerName.endsWith(".mov")) { + return "video"; + } else if (lowerName.endsWith(".mp3") || lowerName.endsWith(".wav") || lowerName.endsWith(".ogg")) { + return "audio"; } return "unknown"; } + /** + * 判断是否为二进制文件格式(不需要读取文本内容) + * 注意:image 类型不在此列,因为图片需要转Base64 + */ + private boolean isBinaryFormat(String format) { + if (format == null) { + return false; + } + return "pdf".equals(format) || "archive".equals(format) || + "video".equals(format) || "audio".equals(format) || "unknown".equals(format); + } + /** * 设置技能图标 */