|
|
@@ -15,6 +15,7 @@ import org.springframework.web.client.RestTemplate;
|
|
|
import javax.annotation.Resource;
|
|
|
import java.io.BufferedReader;
|
|
|
import java.io.File;
|
|
|
+import java.io.FileInputStream;
|
|
|
import java.io.InputStreamReader;
|
|
|
import java.math.BigDecimal;
|
|
|
import java.nio.charset.StandardCharsets;
|
|
|
@@ -134,6 +135,14 @@ public class ReportCollectService {
|
|
|
healthReportDraftService.markCollectFailed(draftId, "无法获取报告文件路径");
|
|
|
return;
|
|
|
}
|
|
|
+ // 文件类型预检:采集链路(指纹引擎/LangGraph/opencode)仅支持 PDF,
|
|
|
+ // 图片等非 PDF 文件直接标记失败,避免 PyPDF2 报 EOF marker not found 等错误
|
|
|
+ if (!isPdfFile(pdfPath)) {
|
|
|
+ log.warn("采集跳过非PDF文件 draftId={}, path={}, filename={}",
|
|
|
+ draftId, pdfPath, draft.getOriginalFilename());
|
|
|
+ healthReportDraftService.markCollectFailed(draftId, "仅支持PDF报告文件,请上传PDF格式");
|
|
|
+ return;
|
|
|
+ }
|
|
|
|
|
|
// 指纹判定
|
|
|
Map<String, Object> fp = fingerprintService.detect(pdfPath, draft.getOriginalFilename());
|
|
|
@@ -201,6 +210,21 @@ public class ReportCollectService {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * 检查文件是否为 PDF(通过魔数 %PDF- 判断)。
|
|
|
+ * 指纹引擎、LangGraph 解析、opencode 均要求 PDF 输入。
|
|
|
+ */
|
|
|
+ private boolean isPdfFile(String filePath) {
|
|
|
+ try (FileInputStream fis = new FileInputStream(filePath)) {
|
|
|
+ byte[] header = new byte[5];
|
|
|
+ int read = fis.read(header);
|
|
|
+ return read == 5 && new String(header, StandardCharsets.US_ASCII).startsWith("%PDF-");
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.debug("PDF魔数检查失败 path={}: {}", filePath, e.getMessage());
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
/** 未知类型:交本地 opencode 服务。因 headless serve 仅单轮文本生成可靠且输出有限,
|
|
|
* 采用分块单轮解析:每一块独立 session、单轮返回该 section 的 JSON,块间互不依赖,
|
|
|
* 最后合并为完整 Payload,避免单轮输出截断导致整单失败。
|