跳至正文

文件上传、解析与摄入任务 ​

本页阅读位置

完成第一轮对话后,按当前业务需求深入。Spring 常规声明优先使用 RegistrationManifest 与注解;本页的底层 register / publish 或直连方法供协议细化与兼容集成参考。

使用前准备 ​

  1. 部署平台,使用应用管理身份创建 mode=MANAGED 的知识草稿版本,并配置分块策略。
  2. 规划文档标识、租户和访问规则。同一文档在同一草稿中同时只接受一个活跃摄入任务。
  3. 上传原件,观察任务;完成后检查解析正文和文档摘要,再发布知识库、授权 Agent。

发布后的知识版本和原件索引关联保持冻结。更新文件需要新的知识草稿版本;不能在已发布版本直接替换。

控制台操作 ​

在“知识库”中选择托管版本,打开“管理托管文档”。“文件摄入”区域支持单件原件上传、任务分页与状态刷新。先填写稳定文档标识,再选择重复策略。平台管理员可明确指定文档租户;应用管理员默认使用可信凭据的租户,不能替其他租户上传。

任务完成后点击“刷新任务与索引”。“原件”和“解析正文”通过当前凭据重新检查权限;必要时可在读取窗口输入真实业务用户凭据,读取后清空该输入。失败时不会显示此前的正文。管理凭据能查看任务元数据,不等于有权读取业务文件。

失败任务显示安全错误代码;先检查格式、配置、容量和当前索引,再显式“重试”。“取消”保留之前已生效的文档索引。终态任务可删除,但仍被任一未撤销知识版本引用的原件不能删除。删除会释放该原件占用,不能恢复该任务的解析历史。

支持格式与资源边界 ​

格式处理注意事项
TXT / MD严格 UTF-8;去除开头 BOM非 UTF-8、空正文和 NUL 字符拒绝;Markdown 仍按草稿分块策略验证
PDFPDFBox 逐页提取;无文本页走 OCR加密/禁止提取、超过 100 页、尺寸异常和超时拒绝
DOCXPOI 提取段落与表格正文不执行宏、嵌入对象、脚本或外部引用
XLSXPOI 读取工作表与存储的单元格显示值不计算公式、不访问外部数据源;以解析后的字符定位,不能承诺原表格版面
PPTXPOI 提取幻灯片正文页码为幻灯片序号;不执行动画、宏和嵌入对象
PNG / JPG / JPEGTesseract OCR每张最多 1600 万像素;OCR 质量依赖扫描质量与语言包

每原件 1 字节至 4 MiB,multipart 请求最大 5 MiB、元数据最大 8 KiB。解析结果最多 65536 个 UTF-16 字符、100 页,Office 解压总量最多 16 MiB、2000 个条目。单解析 Java 子进程堆 192 MiB、元空间 96 MiB,最长 20 秒;OCR 单次最长 15 秒且限制线程。进程资源限制与总体部署容量都需要考虑:最多 2 个同时解析,OCR 内存受容器/操作系统限制,不能只按平台主 Java 堆计算容量。

跨页分块只返回准确的 UTF-16 定位;只有整个片段位于单页时才返回 page。DOCX/XLSX 的解析页不是原文件印刷页。不能把解析结果理解成像素级版面复原或 OCR 正确率承诺。

Docker 与本地部署 ​

项目 Dockerfile 安装 Tesseract 和 eng / chi_sim 语言包,默认启用中英文 OCR;宿主直接运行 Jar 时必须自行准备真实引擎。

环境变量默认作用
SPARKTIDE_INGESTION_CAPACITY_BYTES67108864实例原件字节额度;4 MiB–1 GiB;Base64 与数据库开销另计
SPARKTIDE_DOCUMENT_PARSERbuiltin运维选择的 ServiceLoader 解析器标识;不能从上传请求选择插件
SPARKTIDE_OCR_EXECUTABLE宿主空;镜像 /usr/bin/tesseract绝对可执行文件路径;未配置时扫描页和图片以 OCR_NOT_CONFIGURED 失败
SPARKTIDE_OCR_LANGUAGES宿主 eng;镜像 eng+chi_sim已安装的语言包名称组合
SPARKTIDE_INGESTION_AUTOtrue自动任务协调;生产必须启用,false 仅用于隔离验证

原件 Base64 与解析版本保存在数据库,不使用用户文件名拼接服务器目录。解析临时目录由服务器创建,处理结束删除;容器以非 root 运行。新增 V13 表随全库备份一起备份,禁止仅备份 st_document。原件可能含业务数据,数据库及备份需要组织已有的访问控制和加密磁盘。

依赖版本与兼容依据在平台决策记录中。插件实现 DocumentParser,通过 META-INF/services/dev.sparktide.parser.DocumentParser 注册,加入部署包后由运维配置标识;插件仍受子进程堆、超时、输出上限和环境隔离约束。必须自行验证插件的格式支持与许可,不允许从上传文件加载代码。

HTTP 上传与查询 ​

bash
curl -X POST "$PLATFORM/v1/apps/$APP/knowledge/project-documents/versions/1.0.0/ingestions" \
  -H "Authorization: Bearer $APP_MANAGER" \
  -F 'file=@manual.pdf;type=application/octet-stream' \
  -F 'metadata={"documentId":"manual","title":"用户手册","duplicatePolicy":"UPSERT"};type=application/json'

202 只表示已持久接收,不是解析成功。保存返回 id,再查询任务,不要因网络断开自动重发上传。元数据只允许 documentId、title、source、tenantId、duplicatePolicy、expectedDocumentVersion;未填 title 时使用文件名,source 默认空,tenantId 默认可信凭据租户,duplicatePolicy 默认 UPSERT。文档标识允许 1–128 个字母、数字、点、下划线或横线,禁止单独 . / ..。条件原文版本为 64 位小写 SHA-256。

设 P=/v1/apps/{app}/knowledge/{knowledgeId}/versions/{version}/ingestions:

方法与地址用途条件
POST P上传单件 file 与 JSON metadata part管理身份、MANAGED 草稿;202
GET P?limit=20&offset=0任务分页管理身份;limit 1–100,offset 0–1000000
GET P/当前任务元数据管理身份;不含原件/正文/内部身份快照
POST P/{jobId}/cancel取消活跃任务管理身份;If-Match=当前 revision
POST P/{jobId}/retry显式重试失败任务管理身份、草稿;If-Match;重新检查权限和配置
DELETE P/删除终态任务与未被引用的原件管理身份;If-Match;未撤销索引引用时 409 ORIGINAL_IN_USE
GET P/{jobId}/original鉴权下载原件当前文档 ACL、租户、业务 READ_HISTORY;octet-stream、attachment、no-store
GET P/{jobId}/parsed鉴权读取解析正文同原件权限,已有成功解析版本;UTF-8 text/plain、no-store

草稿原件与正文只允许管理身份读取,仍必须满足当前文档 ACL 与租户;发布后业务身份可按授权读取。filename/title/source 等元数据不是授权依据。source 不会被自动请求。所有 API 使用 Bearer 鉴权,无匿名文件链接或 Cookie 下载旁路。任务查询可以在草稿中使用;撤销知识版本、停用应用、撤销凭据或文档 ACL 后,原件与正文读取被拒绝。

状态与版本 ​

QUEUED → PARSING → INDEXING → SUCCEEDED。失败进入 FAILED,取消进入 CANCELLED;任务修订号随状态变更递增。原件与原始散列不会因 retry 改变;attempt 增加并按当前草稿配置重新解析。取消与过时执行器都不能写入索引。执行器失联后标记 INGESTION_WORKER_LOST,显式重试而不透明重放。

成功结果分为 INDEXED(索引已更新)、UNCHANGED(相同正文与策略)和 SKIPPED(保留原索引)。parsedDocumentVersion 是本次解析候选的规范文档散列,parsedContentHash 是解析正文散列,originalHash 是原件字节散列;result.documentVersion 是当前索引文档版本。SKIPPED 时这两种文档版本可能不同,本次原件不能被当成当前回答来源。只有真正 INDEXED 的原件会成为当前文档 ingestion 引用。

原件、解析版本、索引与任务终态事务一致。损坏文件、分块错误、权限改变、草稿定义改变或并发文档修改均保留之前有效索引。任务活跃时禁止发布;解析完成不自动发布,不切换 Agent,也不进行向量/Embedding 处理。

SDK 示例 ​

java
var upload = DocumentUpload.fromFile("manual", Path.of("manual.pdf"))
    .title("用户手册")
    .duplicatePolicy(DocumentDuplicatePolicy.UPSERT)
    .build();
var job = managerClient.uploadDocument("project-documents", "1.0.0", upload)
    .toCompletableFuture().get();
var current = managerClient.ingestion("project-documents", "1.0.0", (String) job.get("id"))
    .toCompletableFuture().get();
// 确认 SUCCEEDED 后,由有权读取该租户文档的业务身份读取。
byte[] original = readerClient.ingestionContent("project-documents", "1.0.0", (String) job.get("id"), true)
    .toCompletableFuture().get();
kotlin
val upload = documentUpload("manual", Path.of("manual.pdf")) {
    title = "用户手册"
    duplicatePolicy = DocumentDuplicatePolicy.UPSERT
}
val job = managerClient.uploadDocumentAwait("project-documents", "1.0.0", upload)
val current = managerClient.ingestionAwait("project-documents", "1.0.0", job["id"] as String)
val text = readerClient.ingestionContentAwait("project-documents", "1.0.0", job["id"] as String, original = false)
    .toString(Charsets.UTF_8)

Java 示例说明:

DocumentUpload 保存本地原件的有界不可变快照;数组和元数据不能从外部修改。客户端不自动轮询或重试上传。使用 ingestions 分页、cancelIngestion / retryIngestion / deleteIngestion 时传入当前 revision;412 时回读状态并重新确认。ingestionContent 的 original=false 返回 UTF-8 解析正文的 byte[]。

Kotlin 示例说明:

挂起接口桥接 SDK 请求,不把管理身份变成用户身份。业务读取需使用 forUser 配置实际凭据;客户端提交的租户不会替代认证身份。

失败处理 ​

错误处理
FILE_TOO_LARGE / PARSED_CONTENT_LIMIT拆分文件,不盲目提高全部 JSON API 限制
DOCUMENT_PARSE_FAILED / ENCRYPTED_DOCUMENT确认真实格式、解密后另行上传;平台不接受解密密码
OCR_NOT_CONFIGURED / OCR_FAILED / OCR_TIMED_OUT部署真实引擎与语言包,检查扫描图;人工确认后重试
OFFICE_EXPANSION_LIMIT / UNSAFE_OFFICE_ARCHIVE使用可信来源重新导出普通 OOXML 文件
KNOWLEDGE_DRAFT_CHANGED / DOCUMENT_VERSION_MISMATCH回读当前定义或索引,确认是否仍需重试
INGESTION_IN_PROGRESS等待现有任务或取消后再上传
INGESTION_STORAGE_LIMIT / INGESTION_JOB_LIMIT清理不再需要且未被索引引用的终态任务,或调整部署容量
REVISION_MISMATCH回读任务最新 revision;不要自动覆盖并发操作
DOCUMENT_NOT_AVAILABLE / BUSINESS_PERMISSION_DENIED核实当前身份与业务授权,不使用管理员绕过正文限制

同步文本导入、分块预览和跨版本重建继续按原合同使用。向量检索、附件聊天和质量评估属于独立能力,不能由文件摄入成功推定已实现。

文档来源与验证记录
字段内容
状态已确认
日期2026-10-01
来源FileIngestion / ParserProcess / IngestionApi / DocumentUpload
责任人SparkTide 维护者
关联任务完整产品落地 K01
结论上传得到持久任务;只有 SUCCEEDED 且 result.status=INDEXED 才替换当前文档索引
证据平台 169 项、后台 SDK 实际联调 93 项全部通过;PostgreSQL 容器扫描 PDF/PNG OCR、重启保留及控制台撤权验证通过
适用版本:0.1 发布线 · 最近核对:2026-10-09 · SparkTide 产品文档

汇聚智能,驱动涌现。