- 后端
- AI 应用
- NLP
【免费下载链接】xberg
Polyglot document intelligence with a Rust core: extract text, metadata, images, tables, and structured data from 106 formats across 140 file extensions, plus code intelligence for 371 languages. Fifteen bindings, with CLI, REST API, and MCP server.
本篇指南以 Xberg 仓库中 Dart 语言的 XLSX 冒烟测试片段(smoke_xlsx_basic.md)为主体,逐行拆解其在纯 Dart / Flutter 环境下通过 flutter_rust_bridge 调用 Rust 内核提取.xlsx电子表格数据的完整流程。读完本文,你将掌握RustLib初始化与释放的生命周期管理、ExtractInput与ExtractionConfig的 JSON 构造方式、XbergBridge.extract的底层调用链,以及如何通过端到端测试断言验证表格内容、工作表数量与工作表名称等元数据。
测试片段定位:alef 自动生成的多语言冒烟测试
该文档位于docs-site/src/snippets-generated/dart/smoke/目录,属于 Xberg 文档站中由 alef 工具链自动生成的代码片段(文件头部注释明确标注 "This file is auto-generated by alef — DO NOT EDIT.")。这类片段服务于两类场景:
- 类型检查:frontmatter 中
level: typecheck表示该片段会作为 Dart 源码参与编译级校验,确保绑定 API 的签名在代码生成后仍然有效; - 端到端测试:
side_effect: server表明该测试在运行时会启动(或连接)一个 mock server 提供远程文档,验证uri形式的提取输入。
同一目录下还有smoke_docx_basic.md、smoke_pdf_basic.md、smoke_image_png.md等姊妹片段,它们共享同一套 Dart 代码骨架(RustLib.init()→extract→RustLib.dispose()),仅输入 JSON 的mime_type与uri不同。XLSX 片段的核心在于:用一段 20 行左右的代码,验证了「远程 URI 输入 → 默认配置 → 表格文档提取 → 元数据读取」整条通路。
代码逐行拆解
1. 原生运行时初始化:RustLib.init()
import 'dart:io'; import 'package:xberg/xberg.dart'; import 'package:xberg/src/xberg_bridge_generated/frb_generated.dart' show RustLib;XbergBridge的所有方法都通过 flutter_rust_bridge(FRB)桥接到 Rust 内核(仓库中的核心 crate 为crates/xberg)。RustLib.init()负责加载平台原生动态库(Linux 为libxberg_dart.so,macOS 为libxberg_dart.dylib,Windows 为xberg_dart.dll),其解析逻辑集中在 native_loader.dart:
- 缓存路径:按
<cache>/xberg/<version>/<rid>/组织,例如 Linux x64 对应linux-x64RID; - 下载与校验:若本地缓存缺失,会从 release 资产下载对应平台的 tar.gz,并比对发布侧的
.sha256摘要文件,校验失败会直接拒绝安装(Refusing to install a native library that does not match its published checksum); - 开发捷径:环境变量
FRB_DART_LOAD_EXTERNAL_LIBRARY_NATIVE_LIB_DIR可指向本地原生库目录,跳过下载(测试/开发场景)。
2. 构造输入:createExtractInputFromJson
final input = await createExtractInputFromJson(json: '{"kind":"uri","mime_type":"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet","uri":"https://example.com/xlsx/stanley_cups.xlsx"}');输入 JSON 包含三个字段,对应 Rust 侧ExtractInput的序列化结构:
| 字段 | 取值 | 含义 |
|---|---|---|
kind | uri/bytes | 输入来源。uri表示远程地址,bytes表示内存字节流 |
mime_type | application/vnd.openxmlformats-officedocument.spreadsheetml.sheet | XLSX 的标准 MIME 类型,帮助提取器在内容探测之外快速路由 |
uri | 远程文件地址 | 本次冒烟测试指向stanley_cups.xlsx(NHL 球队斯坦利杯数据表) |
在 xberg.dart 的扩展实现中,ExtractInputKind的 wire 值即为'uri'/'bytes'(见ExtractInputKindWireValue),与 JSON 字符串一一对应,这是从 Dart 侧直接把 JSON 文本反序列化为 Rust 强类型对象的基础。
3. 默认配置:createExtractionConfigFromJson(json: '{}')
final config = await createExtractionConfigFromJson(json: '{}');空对象{}表示全部使用 Rust 侧默认值。ExtractionConfig是生成的数据类、本身没有默认值,因此官方推荐从 JSON 构建:凡是省略的字段都保持 Rust 内核的默认配置。这意味着本次冒烟测试考察的是「零配置开箱即用」的 XLSX 提取体验,与生产环境按需配置(如开启 OCR、限定页数、调整表格模型)形成对比。
4. 核心调用:XbergBridge.extract
final result = await XbergBridge.extract(input, config: config); stdout.writeln(result.results[0].metadata);XbergBridge.extract的 Dart 实现(xberg.dart)非常薄:当config为空时,它会自动补上createExtractionConfigFromJson(json: '{}'),然后委托给rust_bridge.extract。返回的ExtractionResult.results是文档数组,本次测试只读取第一个结果(results[0])并打印其metadata—— 这正是本测试片段关注的输出面。
5. 收尾:RustLib.dispose()
} finally { RustLib.dispose(); }通过try / finally保证无论提取是否抛错,原生运行时都会被释放,避免在长驻服务或测试进程中泄漏 FFI 资源。这是所有 Dart 绑定用法的标准收尾模式。
端到端测试中的完整断言链
代码片段本身只打印metadata,但仓库中的端到端测试补全了全部验证点。在 smoke_test.dart 中,同名测试「Smoke test: XLSX with basic spreadsheet data including tables」以XbergBridge.extract的真实返回值做了一组断言:
- MIME 类型回显:
results[0].mimeType必须等于application/vnd.openxmlformats-officedocument.spreadsheetml.sheet; - 内容长度:
content.length >= 100,确保提取出的文本足够充实; - 内容关键词:
content必须同时包含Team、Location、Stanley Cups、Blues、Flyers、Maple Leafs以及球队缩写STL、PHI、TOR—— 这证明表头与单元格值都进入了提取结果; - 表格结构:
results[0].tables.length >= 1,确认表格被结构化识别; - Excel 元数据:
metadata.format.excel.sheet_count >= 2,且sheet_names中包含'Stanley Cups'。
对应地,format_specific_test.dart 中的「XLSX spreadsheet extraction using extract」也复用了同一份stanley_cups.xlsx,验证格式专项路径的提取不报错。
这些断言的契约源头是 fixture 文件 xlsx_basic.json:它声明了 mock 响应路径/xlsx/stanley_cups.xlsx(返回application/octet-stream原始字节),并将上述断言以equals、min_length、contains_all、count_min、greater_than_or_equal等声明式规则固化下来。也就是说,文档片段、fixture 契约与端到端测试三者由同一套生成链路(alef e2e generate)保持一致。
Rust 内核侧:Excel 提取器如何工作
按扩展名分派的读取入口
Dart 绑定只负责参数编解码,真正的提取逻辑在 Rust 内核。入口位于 excel/open.rs 的read_excel_file:它根据文件扩展名把请求分派给不同读取器——
.xlsx/.xlsm/.xltm→read_xlsx_family_file(calamine XLSX 读取器 + sheet 修订与批注合并);.xlam/.xla→ 加载项专用读取路径(解析失败时回退为空工作簿);.xlsb→ calamine Xlsb 二进制工作簿读取器;.ods及其他 →open_workbook_auto自动探测。
ZIP 安全预检
XLSX 本质是 ZIP 容器,因此在进入 calamine 之前,validate_zip_container(excel/open.rs)会先解析 ZIP 中央目录并施加两层防护:
- 条目数不得超过
SecurityLimits::max_files_in_archive; - 累计解压大小与压缩比不得超过
max_archive_size/max_compression_ratio(复用ZipBombValidator)。
注释明确指出,这是为了在 calamine 内部读取路径之前拦截「zip 炸弹」,且解析中央目录不会解压任何条目,属于廉价的预检。
Excel 元数据模型
冒烟测试打印的metadata对应 Rust 侧ExcelMetadata(types/metadata.rs),字段与端到端断言完全对应:
pub struct ExcelMetadata { pub sheet_count: Option<u32>, // 工作簿中的工作表数量 pub sheet_names: Option<Vec<String>>, // 所有工作表的名称 }在 Dart 端,metadata.format以FormatMetadata_Excel判别体出现,其field0即承载这两个字段——这正是smoke_test.dart中(result.results[0].metadata.format as FormatMetadata_Excel).field0.sheetCount断言的访问路径。
如何运行这个测试
安装 Dart 包
dart pub add xberg # 纯 Dart 项目 flutter pub add xberg # Flutter 项目包版本与依赖约束见 pubspec.yaml:SDK 要求>=3.11.0 <4.0.0,运行时基于flutter_rust_bridge2.13.0。首次运行时原生库会按平台 RID 自动下载并校验(见上文native_loader.dart)。
运行冒烟测试
# 在 e2e/dart 目录下(需要 mock server 与 SUT) dart test test/smoke_test.dart --name "XLSX"测试通过SUT_URL/MOCK_SERVER_URL环境变量或本地http://localhost:8008定位 mock server(见 smoke_test.dart),也可以借助 run-with-mock-server.sh 一键拉起整套环境。片段中的https://example.com/...是占位地址,真实运行时由 mock 响应替换。
快速自验示例
若不依赖 mock server,可把片段改造为本地文件输入:
import 'package:xberg/xberg.dart'; Future<void> main() async { final output = await XbergBridge.extract( const ExtractInput(kind: ExtractInputKind.uri, uri: 'stanley_cups.xlsx'), ); print(output.results.first.content); }该模式与 README.md 的 Quick Start 一致:ExtractInput未指定mime_type时,Rust 侧会执行格式探测后自动路由。
从冒烟测试走向生产配置
冒烟测试验证的是默认路径,而真实项目通常需要精细控制。同类测试(如config_*系列 fixture)展示了可扩展的配置面,例如:
final config = await createExtractionConfigFromJson(json: ''' { "output_format": "markdown", "ocr": {"backend": "tesseract", "language": ["eng"]}, "table": {"model": "tatr"} } ''');其 Rust 侧默认值、字段枚举(如TableModel、OutputFormat)均可从 xberg.dart 中生成的扩展方法(TableModelWireValue、ExtractionMethodWireValue等)逐一对齐 wire 值。需要批量处理时,还可改用XbergBridge.extractBatch(inputs)并行提取多个文档。
小结
通过这一份 20 行的 Dart 冒烟测试片段,可以完整透视 Xberg 的多语言绑定架构:Dart 层负责 JSON 编解码与 FFI 生命周期,Rust 内核负责格式分派、安全预检与结构化解构,alef 生成链路则把同一测试契约同步到文档片段、fixture 与端到端断言。对于 XLSX 场景,默认配置下即可获得文本内容、结构化表格、工作表数量与名称四类产物,为后续的 RAG 切块、表格问答与元数据索引提供了可直接消费的输入。
- 后端
- AI 应用
- NLP
【免费下载链接】xberg
Polyglot document intelligence with a Rust core: extract text, metadata, images, tables, and structured data from 106 formats across 140 file extensions, plus code intelligence for 371 languages. Fifteen bindings, with CLI, REST API, and MCP server.
相关推荐
使用 C 绑定提取 XLSX 电子表格:Xberg 冒烟测试代码实战解析
使用 C 绑定提取 XLSX 电子表格:Xberg 冒烟测试代码实战解析 本文以 Xberg 仓库中的 C 冒烟测试片段( docs site/src/snip
后端AI 应用NLP使用 xberg 的 Dart 绑定提取 XLSX 电子表格:extract API 实战指南
使用 xberg 的 Dart 绑定提取 XLSX 电子表格:extract API 实战指南 本篇技术指南以仓库中自动生成的 Dart 示例文档 format
后端AI 应用NLPXberg Dart 绑定 JSON 文档提取:smoke_json_basic 冒烟测试逐行解析
Xberg Dart 绑定 JSON 文档提取:smoke_json_basic 冒烟测试逐行解析 本指南围绕 Xberg 仓库中的 Dart 冒烟测试片段 s
后端AI 应用NLP
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考