diff --git a/src/main/java/com/genersoft/iot/vmp/aiot/service/impl/AiScreenshotServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/aiot/service/impl/AiScreenshotServiceImpl.java index ddad80594..478469f3a 100644 --- a/src/main/java/com/genersoft/iot/vmp/aiot/service/impl/AiScreenshotServiceImpl.java +++ b/src/main/java/com/genersoft/iot/vmp/aiot/service/impl/AiScreenshotServiceImpl.java @@ -210,8 +210,15 @@ public class AiScreenshotServiceImpl implements IAiScreenshotService { String url = (String) data.get("url"); writeCache(cameraCode, url); - // 持久化 cos_key 到 DB(永不过期,供后续直接读取) - String cosKey = pendingCosKeys.remove(requestId); + // 从URL解析cos_key(优先),失败时降级使用pendingCosKeys + String cosKey = extractCosKeyFromUrl(url); + if (cosKey == null) { + cosKey = pendingCosKeys.remove(requestId); + } else { + // 解析成功,也要清理pendingCosKeys避免内存泄漏 + pendingCosKeys.remove(requestId); + } + if (cosKey != null) { try { snapshotMapper.upsert(cameraCode, cosKey); @@ -219,6 +226,8 @@ public class AiScreenshotServiceImpl implements IAiScreenshotService { } catch (Exception e) { log.error("[AI截图] 持久化 cos_key 失败: cameraCode={}, error={}", cameraCode, e.getMessage()); } + } else { + log.warn("[AI截图] 无法获取cos_key: cameraCode={}, url={}", cameraCode, url); } } else { pendingCosKeys.remove(requestId); @@ -233,6 +242,48 @@ public class AiScreenshotServiceImpl implements IAiScreenshotService { } } + /** + * 从COS预签名URL中提取cos_key + * URL格式: https://{bucket}.cos.{region}.myqcloud.com/{cos_key}?q-sign-... + * 返回: snapshots/{camera_code}/2026-03-10/08-16-39_xxx.jpg + */ + private String extractCosKeyFromUrl(String url) { + if (url == null || url.isEmpty()) { + return null; + } + try { + // 移除查询参数,得到路径部分 + String pathPart = url; + int queryStart = url.indexOf('?'); + if (queryStart > 0) { + pathPart = url.substring(0, queryStart); + } + + // 找到myqcloud.com后的路径 + int domainEnd = pathPart.indexOf(".myqcloud.com/"); + if (domainEnd > 0) { + String cosKey = pathPart.substring(domainEnd + ".myqcloud.com/".length()); + // 确保以snapshots/开头 + if (cosKey.startsWith("snapshots/")) { + return cosKey; + } + } + + // 降级:尝试最后一个/后的路径 + int lastSlash = pathPart.lastIndexOf('/'); + if (lastSlash > 0) { + // 往回找snapshots + int snapshotsIdx = pathPart.indexOf("snapshots/"); + if (snapshotsIdx > 0) { + return pathPart.substring(snapshotsIdx); + } + } + } catch (Exception e) { + log.warn("[AI截图] 从URL解析cos_key失败: {}, error={}", url, e.getMessage()); + } + return null; + } + /** * 写入截图缓存 */