news 2026/10/24 1:20:31

Xberg PHP 绑定实战:用 `extract` API 通过 Bytes 字节流提取 PDF 文档内容

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Xberg PHP 绑定实战:用 `extract` API 通过 Bytes 字节流提取 PDF 文档内容
  • 后端
  • 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.

项目地址:https://gitcode.com/gh_mirrors/kr/xberg
点击查看免费下载

Xberg 是一个以 Rust 为核心的多语言文档智能引擎,PHP 绑定为其提供了 PHP 8.2+ 的类型安全接口。本文围绕仓库中的 contract 契约文档 api_extract_bytes_input.md 展开,完整讲解「Bytes 字节流输入」这条extract调用链:如何构造ExtractInput、如何以内存字节而非文件路径方式喂给提取引擎、如何读取mimeType与content等结果字段,并对比 URI 输入与批量提取(extractBatch)两种扩展形态。读完本文,你将能够在 PHP 项目中直接对上传的二进制文档(如 PDF、图片、Office 文件)执行无落盘的内容提取,并理解其底层契约与测试验证方式。

一、Bytes 输入提取是什么,为什么需要它

Xberg 的提取入口接收ExtractInput作为唯一输入描述。从仓库中的契约文档 api_extract_bytes_input.md 可以看到,最核心的调用只有两行:

use Xberg\Xberg; use Xberg\ExtractInput; $input = \Xberg\ExtractInput::from_json(json_encode(["bytes" => "pdf/fake_memo.pdf", "filename" => "fake_memo.pdf", "kind" => "bytes"])); $result = Xberg::extract($input, null);

kind字段取值为"bytes",表示本次提取的输入是内存中的字节流而非磁盘路径或远程 URI。这在 Web 场景中非常实用:用户上传文件后,PHP 拿到的是$_FILES里的临时文件内容(file_get_contents即可读出),无需先落盘再交给提取引擎,既省去了临时文件管理,也避免了对服务器文件系统的依赖。

对应的契约 fixture fixtures/contract/api_extract_bytes_input.json 给出了这个调用的完整「输入 + 断言」定义:

  • call为extract;
  • input.kind为"bytes",input.bytes是一段完整的 PDF 字节数组(即测试文档fake_memo.pdf),input.filename为"fake_memo.pdf";
  • 断言要求results[0].mime_type等于"application/pdf"、results[0].content长度不小于 10,且内容中包含"May 5, 2023"或"Mallori"。

也就是说,只要把二进制 PDF 以字节形式传入,引擎就能自动识别格式、抽出正文文本并返回 MIME 类型——格式探测、解析、抽取全部在内部完成。

二、ExtractInput 的字段解析与构造方式

从契约文档与 fixture 可以归纳出 Bytes 输入下ExtractInput的核心字段:

字段取值含义与说明
kind"bytes"输入形态标记,告知引擎按字节流处理;另见"uri"(见下文第四节)
bytes字节数组文档的原始二进制内容。测试 harness 中以 JSON 数组形式给出,实际 PHP 场景中可用file_get_contents()获得字符串后交由绑定层编码
filename字符串逻辑文件名(如fake_memo.pdf),用于辅助格式识别与结果元数据
mimeType字符串(可选)显式声明 MIME 类型,如"application/pdf";不提供时引擎自动探测

补充mimeType的写法在 extract/extract_bytes_input.md 中给出,注意其命名空间形式\Xberg\ExtractInput::from_json(...):

use Xberg\Xberg; use Xberg\ExtractInput; $input = \Xberg\ExtractInput::from_json(json_encode(["bytes" => "pdf/fake_memo.pdf", "filename" => "fake_memo.pdf", "kind" => "bytes", "mimeType" => "application/pdf"])); $result = Xberg::extract($input, null); var_dump($result->getResults()[0]->mimeType); var_dump($result->getResults()[0]->content);

这里有两个值得注意的细节:

  1. from_json是绑定层提供的结构化构造入口:PHP 侧用json_encode将关联数组转成 JSON 字符串,再交给from_json反序列化为类型安全的ExtractInput对象,避免手写繁琐的属性赋值。这是契约 fixture 与 e2e 测试统一使用的构造方式。
  2. Xberg::extract的第二参数传null表示使用默认配置:在快速验证场景中可以直接传null;需要精细化控制时则传入ExtractionConfig对象(见第四节批量示例)。

fixture extract/extract_bytes_input.json 与 contract 版本略有差异:它额外携带"mime_type": "application/pdf"顶层字段,断言改为not_error、mime_type精确匹配与content长度不小于 50。这说明「带上明确的 MIME 声明」同样是一条被 e2e 覆盖的合法路径,可减少格式探测的不确定性。

三、读取提取结果:getResults 与核心字段

Xberg::extract返回的是包含一组结果的输出对象,通过getResults()[0]取得第一个文档结果。契约文档演示了最常用的两个字段:

var_dump($result->getResults()[0]->mimeType); var_dump($result->getResults()[0]->content);
  • mimeType:识别出的文档 MIME 类型,如application/pdf。该字段在 fixture 断言中被精确校验,是验证输入是否正确被识别的最直接信号;
  • content:抽取出的正文文本。contract fixture 断言其长度不小于 10 且包含关键内容("May 5, 2023"或"Mallori"),确保的不是「返回了非空字符串」,而是「抽取到了真实文档内容」。

从 packages/php/README.md 的 Quick Start 可以进一步看到结果对象携带的更多能力:$result->content(正文)、$result->metadata?->title(标题)、$result->metadata?->authors(作者)、$result->metadata?->pdf?->page_count(PDF 页数)、$result->mimeType(格式)以及$result->tables(表格数组,含pageNumber与markdown渲染)。也就是说,Bytes 输入与 URI/路径输入的返回结构完全一致——提取引擎对输入形态透明,结果永远是统一的ExtractedDocument。

<?php declare(strict_types=1); require_once __DIR__ . '/vendor/autoload.php'; $output = \Xberg\XbergApi::extract(\Xberg\ExtractInput::fromUri('document.pdf'), $config ?? \Xberg\ExtractionConfig::default()); $result = $output->getResults()[0]; echo "Extracted Content:\n"; echo "==================\n"; echo $result->content . "\n\n"; echo "Metadata:\n"; echo "=========\n"; echo "Title: " . ($result->metadata?->title ?? 'N/A') . "\n"; echo "Authors: " . (isset($result->metadata?->authors) ? implode(', ', $result->metadata?->authors) : 'N/A') . "\n"; echo "Pages: " . ($result->metadata?->pdf?->page_count ?? 'N/A') . "\n"; echo "Format: " . $result->mimeType . "\n\n";

这段示例还揭示了一个 API 形态细节:绑定同时提供Xberg静态门面与XbergApi门面两种调用方式,契约 fixture 使用Xberg::extract($input, null),而 README 中的面向对象示例使用\Xberg\XbergApi::extract(...),二者指向同一套提取语义,可按项目风格选用。

四、与其他输入形态对比:URI 与批量提取

Bytes 并不是唯一的输入形态。契约文档目录下并存的 api_extract_uri.md 展示了kind = "uri"的写法:

use Xberg\Xberg; use Xberg\ExtractInput; $input = \Xberg\ExtractInput::from_json(json_encode(["kind" => "uri", "uri" => "https://example.com/pdf/fake_memo.pdf"])); $result = Xberg::extract($input, null); var_dump($result->getResults()[0]->content);

区别一目了然:Bytes 形态传bytes+filename,URI 形态传uri。前者适合内存数据(上传文件、缓存内容),后者适合由引擎直接拉取的远程资源(注意该 fixture 的side_effect标记为server,而 Bytes 版本的side_effect是safe——不发起到外部网络的副作用)。生产代码中,用ExtractInput::fromUri(...)与ExtractInput::fromBytes(file_get_contents(...), 'text/plain', 'note.txt')这两条便捷构造器即可分别表达两种形态。

当需要一次处理多个文档时,契约文档提供了批量入口extractBatch(见 api_extract_batch_bytes.md),其字节输入写法与单条extract完全同构,并显式传入ExtractionConfig:

use Xberg\Xberg; use Xberg\ExtractInput; use Xberg\ExtractionConfig; $result = Xberg::extractBatch([ExtractInput::from_json('{"bytes":"pdf/fake_memo.pdf","filename":"fake_memo.pdf","kind":"bytes"}')], \Xberg\ExtractionConfig::from_json('{}')); var_dump($result->getResults()[0]->mimeType); var_dump($result->getResults()[0]->content);

注意三点差异:参数由单个ExtractInput变为数组;第二个参数由null变为\Xberg\ExtractionConfig::from_json('{}')(空配置对象,等价于默认配置的显式形式);返回对象同样通过getResults()取结果数组,其summary->results字段(README 批量示例可见)可报告处理文档总数。README 中的完整批量用法为:

<?php declare(strict_types=1); require_once __DIR__ . '/vendor/autoload.php'; use Xberg\Xberg; use Xberg\ExtractInput; use Xberg\ExtractionConfig; $inputs = [ ExtractInput::fromUri('document1.pdf'), ExtractInput::fromUri('document2.docx'), ExtractInput::fromBytes(file_get_contents('note.txt') ?: '', 'text/plain', 'note.txt'), ]; $config = new ExtractionConfig( extractTables: true, extractImages: false, ); $output = Xberg::extractBatch($inputs, $config); echo "Processed {$output->summary->results} documents\n"; foreach ($output->getResults() as $result) { echo "Content: " . strlen($result->content) . " chars\n"; echo "Tables: " . count($result->tables) . "\n"; echo "MIME: {$result->mimeType}\n\n"; }

这里ExtractInput::fromBytes($bytes, $mimeType, $filename)正是「Bytes 输入」的面向对象便捷构造器——三个参数恰好对应契约字段bytes、mimeType、filename,kind由绑定层自动补齐为"bytes"。

五、底层实现与契约来源:Rust 引擎 + 绑定桥

Bytes 输入之所以能在 PHP 侧保持如此精简,是因为真正的解析与抽取全部发生在 Rust 核心中。PHP 绑定通过绑定桥把ExtractInput/ExtractionConfig序列化后传递给共享的 Rust 实现——packages/php/README.md 明确指出「Same engine as every binding」,Rust、Python、Node.js、Go、Java、PHP、Ruby、.NET、Elixir、WASM 等 15 种绑定共享同一套实现。

从源码结构还可以印证插件的契约边界: packages/php/src/DocumentExtractor.php 定义了DocumentExtractor插件接口,其extract(ExtractInput $input, ExtractionConfig $config): ExtractedDocument与supported_mime_types(): mixed两个方法,说明自定义提取器/后处理器同样以ExtractInput作为输入描述、以ExtractedDocument作为返回类型——与内置引擎的输入输出模型完全对齐。

值得说明的是,契约文档位于docs-site/src/snippets-generated/php/contract/,其文件头注明由 alef 工具自动生成(This file is auto-generated by alef),是对应 fixture JSON 的「可读 + 可执行」投影。因此这条extract调用链有三重保障:

  1. fixture 定义(fixtures/contract/api_extract_bytes_input.json)给出精确断言;
  2. snippet 文档(api_extract_bytes_input.md)给出可直接复制的 PHP 代码;
  3. e2e 测试(如 e2e/php/tests/ContractTest.php)在真实绑定上执行同一调用并校验断言,保证文档与实现不脱节。

六、边界情况与错误处理

字节输入虽然简单,但输入描述的正确性同样会被契约校验。仓库fixtures/error/目录下与 Bytes 输入直接相关的三个错误场景值得在生产代码中提前防御:

  • error_empty_bytes.json:bytes为空时,引擎应返回错误而非静默产出空结果;
  • error_empty_mime.json:在显式要求 MIME 的路径下,mimeType为空视为非法输入;
  • error_invalid_mime_format.json:MIME 字符串格式非法(如缺失/分隔)同样触发错误分支。

对应地,在 PHP 中建议在调用Xberg::extract前先校验字节非空、文件名非空,并在显式传mimeType时保证其符合type/subtype格式;若依赖自动探测,则filename中的扩展名是重要辅助信号(如fake_memo.pdf之于application/pdf)。

七、完整可运行示例

综合契约文档与 README,给出一个从「读取上传字节」到「输出结果」的完整闭环示例:

<?php declare(strict_types=1); require_once __DIR__ . '/vendor/autoload.php'; use Xberg\Xberg; use Xberg\ExtractInput; // 1. 从磁盘读入字节(Web 场景下等价于读取 $_FILES 上传内容) $pdfBytes = file_get_contents('fake_memo.pdf'); if ($pdfBytes === false || $pdfBytes === '') { throw new RuntimeException('empty bytes input'); } // 2. 构造 Bytes 输入:bytes + filename + kind $input = \Xberg\ExtractInput::from_json(json_encode([ 'bytes' => $pdfBytes, 'filename' => 'fake_memo.pdf', 'kind' => 'bytes', ])); // 3. 调用提取(第二参数传 null 使用默认配置) $result = Xberg::extract($input, null); // 4. 读取结果 $doc = $result->getResults()[0]; printf("MIME: %s\n", $doc->mimeType); printf("Content: %s\n", $doc->content);

将bytes换成真实文件内容、filename换成实际文件名,即可用于任意受支持格式(PDF、DOCX、XLSX、PNG、HTML 等共 107 种格式)。若需要批量或远程输入,把第 3 步替换为Xberg::extractBatch([$input], \Xberg\ExtractionConfig::from_json('{}'))或改传kind => "uri"即可。

八、小结

Bytes 输入是 Xberg PHP 绑定中最直接、最贴合 Web 上传场景的提取形态:一个ExtractInput::from_json(...)构造输入,一次Xberg::extract($input, null)完成提取,getResults()[0]->mimeType与->content拿到结果。本文从契约文档出发,依次剖析了kind/bytes/filename/mimeType四个字段、getResults结果读取、URI 与批量两种扩展形态,并借助 fixtures/contract/api_extract_bytes_input.json 的断言、packages/php/README.md 的完整用法与 packages/php/src/DocumentExtractor.php 的接口定义,将一条契约 snippet 还原成了可对照源码深入验证的完整技术路径。

  • 后端
  • 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.

项目地址:https://gitcode.com/gh_mirrors/kr/xberg
点击查看免费下载
上一篇:Tesla Custom Integration 完整指南:3步在 Home Assistant 中精准追踪车辆与 Powerwall 能源
下一篇:3步精通GitFS:将Git仓库变成实时文件系统的完整指南

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/24 1:20:26

Claude API上下文管理实战:构建外置记忆层与滚动摘要系统

不止一个接入了Claude API的朋友问过我&#xff1a;明明每次请求都是按文档发的&#xff0c;为什么机器人聊多了还是像失忆一样&#xff1f;我一般直接甩一个项目链接过去&#xff0c;里面是一个叫claude-mem的小工具。它的全部工作就一句话&#xff1a;给无状态的对话接口套一…

作者头像 李华
网站建设 2026/10/24 1:20:24

让OmniBot自动干活:定时任务与Subagent后台执行完整玩法

让OmniBot自动干活&#xff1a;定时任务与Subagent后台执行完整玩法 【免费下载链接】OmniBot Your on-phone / mobile AI Agent / Claw, capable of operating terminals and performing a wide range of tasks in the Android world || 你的手机 AI 代理&#xff0c;她可以操…

作者头像 李华
网站建设 2026/10/20 2:35:30

01.02.01.Astra系列 环境搭建篇(CentOS9系统下OpenCV安装配置)

本页目录 1、安装配置2、测试api&#xff1a;https://osgeo.cn/opencv-python/ch01-setup/chapter.html 安装配置参考: 01.01.02.DeepSeek&#xff1a;环境搭建篇&#xff08;安装配置 显卡驱动&#xff09; 01.01.01.DeepSeek&#xff1a;环境搭建篇&#xff08;安装配置 开发…

作者头像 李华