Gotenberg 包会将转换工作委托给外部服务。应用代码应当显式划定服务边界:校验输入、构造载荷、发送请求、解析结果,并处理服务故障。
当你围绕 nextpdf/gotenberg 构建办公文档转 PDF 的转换流程、上传端点、服务健康检查或传输策略时,可以参考本指南。
| 层 | 归属 | 职责 | 不应放置于此 |
|---|
| 上传或文档来源 | 应用 | 授权调用方、校验来源、选择转换策略。 | 服务 URL 或传输固定(pinning)决策。 |
| 格式检测 | nextpdf/gotenberg | 将安全的扩展名映射到 OfficeFormat。 | 在没有应用层校验的情况下信任 MIME 类型。 |
| 桥接 | nextpdf/gotenberg | 构建 multipart 请求、调用 Gotenberg、解析 PDF 响应。 | 领域查询或存储策略。 |
| Gotenberg 服务 | 部署 | 将办公文档转换为 PDF。 | PHP 应用层授权。 |
| 核心引擎 | nextpdf/nextpdf | 可选地导入或合并转换后的 PDF 数据。 | 办公文档转换。 |
| 阶段 | 行为 | 开发者操作 |
|---|
| 配置创建 | 加载 API URL、超时时间、最大大小、API 密钥和固定项(pins)。 | 不要将服务 URL 和令牌写入源代码。 |
| 输入校验 | 检查文件路径、文件大小、文件名、扩展名以及 URL 安全性。 | 在派发之前拒绝不受支持的输入。 |
| 载荷构造 | GotenbergConvertPayload 构建 multipart 表单数据。 | 仅在安全时才保留原始文件名。 |
| 服务请求 | 桥接将请求发送到 /forms/libreoffice/convert。 | 配置超时时间与传输策略。 |
| 结果解析 | GotenbergResponseParser::parse() 返回 PDF 字节与元数据。 | 将非 PDF 或错误响应视为转换失败。 |
| 路径 | 用途 |
|---|
app/Pdf/Conversion/* | 围绕 GotenbergBridge 的应用层封装。 |
app/Pdf/Uploads/* | 上传校验、存储以及文件名策略。 |
app/Pdf/ConversionPolicy/* | 大小、格式以及服务选择策略。 |
tests/Pdf/Conversion/* | 格式、文件、服务以及传输相关的测试。 |
将文件校验与转换分离。转换服务应当接收已经过授权的输入,同时仍将包级校验作为纵深防御。
use NextPDF\Gotenberg\GotenbergBridge;
final readonly class OfficeConversionService
public function __construct(
private GotenbergBridge $bridge,
public function convertUploadedFile(string $safePath): string
$result = $this->bridge->convertFile($safePath);
if (!$result->isValid()) {
throw new RuntimeException('The conversion service did not return a valid PDF.');
| 模式 | API | 适用场景 | 约束 |
|---|
| 转换文件路径 | GotenbergBridge::convertFile() | 文档已经存储在磁盘上。 | 路径必须可读,且经过策略批准。 |
| 转换内存中的字节 | GotenbergBridge::convertString() | 应用已经持有来自上传或对象存储的字节。 | 格式检测仍然由文件名决定。 |
| 直接构建载荷 | GotenbergConvertPayload | 测试或自定义传输代码需要 multipart 字节。 | 生成边界(boundary)时不得使用用户输入。 |
| 直接解析响应 | GotenbergResponseParser::parse() | 自定义 HTTP 调用仍希望使用包级解析。 | 必须传入预期的 OfficeFormat。 |
GotenbergBridge::isAvailable() 是就绪信号。它不应作为唯一的运行时防护。某项服务可能在就绪检查时可用,却在下一次转换时失败。
| 检查项 | 用途 | 运维说明 |
|---|
| 配置有效性 | 检测缺失的 API URL。 | 在应用启动或部署检查期间运行。 |
/health 可用性 | 检测服务是否可达。 | 用于就绪仪表盘。 |
| 小型固定样例转换 | 检测 LibreOffice 损坏或服务回归。 | 在计划内的冒烟测试中运行,而不是每次请求都运行。 |
| 超时监控 | 检测服务变慢。 | 按格式和文件大小跟踪。 |
| 扩展点 | 用于 | 约束 |
|---|
PSR-18 ClientInterface | 自定义 HTTP 客户端行为。 | 必须遵循 PSR-18 的 response/exception 语义。 |
| PSR-17 工厂 | 请求与流的创建。 | 桥接构造时必需。 |
HtmlSecurityPolicyInterface | 针对 HTML 输入的解析层策略。 | 与 Gotenberg 安全策略互为补充。 |
ResponseFactoryInterface | 固定(pinned)cURL 传输的响应构造。 | 仅在使用包级传输路径时才需要。 |
GotenbergSecurityPolicy | URL、文件大小、文件名以及固定项校验。 | 将应用层授权保持在该层之外。 |
- 在测试中先从
convertString() 入手,使固定样例更明确。
- 仅在文件系统路径受控之后,才添加
convertFile()。
- 将最大文件大小保持在服务与基础设施限制之下。
- 将
isAvailable() 用作就绪信号,而不是用来替代错误处理。
- 记录文件名、格式、大小、状态以及耗时。不要记录文档字节。
- 在对外暴露上传端点之前,先添加超时与故障模式相关的测试。
| 故障 | 应在何处处理 | 推荐的响应 |
|---|
| 不受支持的扩展名 | 格式检测。 | 在服务派发之前拒绝。 |
| 不安全的文件名 | 安全策略。 | 拒绝并规范上传命名策略。 |
| 超大文件 | 上传策略与包级校验。 | 在读取或发送大型载荷之前拒绝。 |
| Gotenberg 不可用 | 桥接边界。 | 在适当时返回可重试的应用错误。 |
| 非 PDF 响应 | 响应解析器。 | 将其视为转换失败,并捕获服务状态。 |
| 固定项或 URL 校验失败 | 传输策略。 | 采用失败即关闭(fail closed)策略,并告警运维人员。 |
| 关注点 | 默认值 | 何时覆盖 |
|---|
| 超时时间 | 30 秒。 | 仅在测量真实服务延迟之后才增大。 |
| 最大文件大小 | 52,428,800 字节。 | 对于公共或多租户端点应调低。 |
| API 密钥 | 为空。 | 对于私有 Gotenberg 部署应进行设置。 |
| 受支持的格式 | docx、xlsx、pptx、odt、ods、odp。 | 仅当 OfficeFormat 与解析器支持时,才添加格式。 |
| 固定集(Pin sets) | 为空。 | 添加固定项时,同时配备备用固定项与轮换流程。 |
- 格式测试覆盖受支持与不受支持的扩展名。
- 文件测试覆盖缺失、不可读、超大以及不安全的文件名。
- 服务测试覆盖非 2xx 响应、无效的响应体以及传输异常。
- 安全测试覆盖在策略禁止的情况下使用私有或无效的服务 URL。
- 超时测试断言已配置的超时时间被传递给传输层。
- 固定样例测试将样例文档保持得短小且不含敏感信息。