diff --git a/CHANGELOG.MD b/CHANGELOG.MD index b309f96a5..7a544cda6 100644 --- a/CHANGELOG.MD +++ b/CHANGELOG.MD @@ -2,6 +2,12 @@ 更新日志文档,版本顺序从新到旧,最新版本在最前(上)面。 +# 0.18.3 + +## 问题修复 + +- 更新条目时对于https的封面下载失败时没有保留原封面不更新 + # 0.18.2 - 条目拉取后没有自动将封面下载到本地 diff --git a/gradle.properties b/gradle.properties index e9f68a221..0da9441cf 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1 +1 @@ -version=0.18.2 +version=0.18.3 diff --git a/server/src/main/java/run/ikaros/server/core/attachment/listener/AttachmentSubjectCoverChangeListener.java b/server/src/main/java/run/ikaros/server/core/attachment/listener/AttachmentSubjectCoverChangeListener.java index bfe786a7f..c2d918d61 100644 --- a/server/src/main/java/run/ikaros/server/core/attachment/listener/AttachmentSubjectCoverChangeListener.java +++ b/server/src/main/java/run/ikaros/server/core/attachment/listener/AttachmentSubjectCoverChangeListener.java @@ -2,6 +2,7 @@ import static run.ikaros.api.core.attachment.AttachmentConst.COVER_DIRECTORY_ID; +import java.nio.charset.StandardCharsets; import java.util.Objects; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; @@ -11,6 +12,7 @@ import org.springframework.stereotype.Component; import org.springframework.web.client.RestTemplate; import reactor.core.publisher.Mono; +import reactor.core.scheduler.Schedulers; import run.ikaros.api.core.attachment.AttachmentUploadCondition; import run.ikaros.api.infra.utils.FileUtils; import run.ikaros.api.store.enums.AttachmentReferenceType; @@ -18,6 +20,7 @@ import run.ikaros.server.core.subject.SubjectOperator; import run.ikaros.server.core.subject.event.SubjectRemoveEvent; import run.ikaros.server.core.subject.event.SubjectUpdateEvent; +import run.ikaros.server.infra.utils.ByteArrUtils; import run.ikaros.server.store.entity.AttachmentEntity; import run.ikaros.server.store.entity.AttachmentReferenceEntity; import run.ikaros.server.store.entity.SubjectEntity; @@ -105,8 +108,16 @@ public Mono onSubjectCoverUpdate(SubjectUpdateEvent event) { .then(Mono.just(newCover)) .filter(StringUtils::isNotBlank) .filter(url -> url.startsWith("http")) + .publishOn(Schedulers.boundedElastic()) .flatMap(url -> { byte[] bytes = restTemplate.getForObject(url, byte[].class); + if (bytes == null || !ByteArrUtils.isBinaryData(bytes)) { + log.warn("Download subject cover fail for url: {}", url); + if (ByteArrUtils.isStringData(bytes)) { + log.warn("Response: {}", new String(bytes, StandardCharsets.UTF_8)); + } + return Mono.empty(); + } DataBufferFactory dataBufferFactory = new DefaultDataBufferFactory(); return attachmentService.upload(AttachmentUploadCondition.builder() .parentId(COVER_DIRECTORY_ID) diff --git a/server/src/main/java/run/ikaros/server/infra/utils/ByteArrUtils.java b/server/src/main/java/run/ikaros/server/infra/utils/ByteArrUtils.java new file mode 100644 index 000000000..212699c5e --- /dev/null +++ b/server/src/main/java/run/ikaros/server/infra/utils/ByteArrUtils.java @@ -0,0 +1,31 @@ +package run.ikaros.server.infra.utils; + +import java.nio.charset.StandardCharsets; + +public class ByteArrUtils { + /** + * 判断字节数组为二进制数据. + */ + public static boolean isBinaryData(byte[] data) { + for (byte b : data) { + if (b < 32 && b != 9 && b != 10 && b != 13) { + return true; // 存在控制字符,可能是二进制数据 + } + } + return false; // 没有控制字符,可能是字符串 + } + + /** + * 判断字节数组为字符串数据. + */ + public static boolean isStringData(byte[] data) { + try { + String str = new String(data, StandardCharsets.UTF_8); + // 检查解码后的字符串是否包含非可打印字符 + return str.chars().allMatch(c -> c >= 32 || c == 9 || c == 10 || c == 13); + } catch (Exception e) { + return false; // 解码失败,认为是二进制数据 + } + } + +}