diff --git a/backend-java/src/main/java/com/nanri/aiimage/modules/pricetrack/service/PriceTrackTaskService.java b/backend-java/src/main/java/com/nanri/aiimage/modules/pricetrack/service/PriceTrackTaskService.java index 543c7dd8..8a20f91f 100644 --- a/backend-java/src/main/java/com/nanri/aiimage/modules/pricetrack/service/PriceTrackTaskService.java +++ b/backend-java/src/main/java/com/nanri/aiimage/modules/pricetrack/service/PriceTrackTaskService.java @@ -1463,13 +1463,20 @@ public class PriceTrackTaskService { if (rawPath == null || rawPath.isBlank()) { continue; } - // 只允许解析上传落库的临时目录文件:直接 new File(请求路径) 可被穿越读服务器任意 csv/xlsx - File file = new File(localFileStorageService.localTempRoot().getAbsolutePath(), rawPath); + // 上传文件路径解析(三种形态都过 isInsideTempDir 穿越校验,不放开临时目录外读取): + // ①绝对路径:老客户端提交上传接口返回的 localPath 时按原路径直读; + // ②相对路径/裸文件名:相对上传临时目录拼接; + // ③fileKey/索引键:按上传索引反查临时目录(与去重/转换等模块统一的口径)。 + File file = new File(rawPath); if (!file.isFile()) { - // 传入的是 fileKey/索引键时按上传索引反查临时目录 - File resolved = localFileStorageService.findLocalSourceFile(rawPath); - if (resolved != null) { - file = resolved; + File joined = new File(localFileStorageService.localTempRoot().getAbsolutePath(), rawPath); + if (joined.isFile()) { + file = joined; + } else { + File resolved = localFileStorageService.findLocalSourceFile(rawPath); + if (resolved != null) { + file = resolved; + } } } if (!file.isFile() || !isInsideTempDir(file)) { diff --git a/frontend-vue/src/pages/brand/components/BrandPriceTrackTab.vue b/frontend-vue/src/pages/brand/components/BrandPriceTrackTab.vue index f1f5432b..a39de0cd 100644 --- a/frontend-vue/src/pages/brand/components/BrandPriceTrackTab.vue +++ b/frontend-vue/src/pages/brand/components/BrandPriceTrackTab.vue @@ -569,8 +569,10 @@ async function uploadAsinPathsToJava(paths: Array item.localPath).filter((path) => !!path) + // 提交上传返回的 fileKey(与去重/转换/采集等模块一致):服务端按 key 反查上传临时目录, + // 不依赖上传返回的 localPath 绝对路径形态——安全加固后服务端按拼接解析绝对路径会失败。 + // 仅上传成功(上传接口返回 data)的文件才进入列表,未上传成功不兜底本地路径(服务器无法读取)。 + return asinUploadedFiles.value.map((item) => item.fileKey).filter((path) => !!path) } function resolveCountryCodesForRequest() {