HTTP 转换服务(officia-server)
能力摘要(AI 友好):
officia-server是 Officia 自带的零依赖 HTTP 转换服务,用 JDK 内置 HttpServer 把常用门面包成 REST 接口:Word → PDF / OFD、OFD → PDF / 文本、OFD 电子发票解析、OFD 签章验证、PDF → 文本 / Word。一个可执行 jar 或一个 Docker 镜像即可部署,适合非 Java 技术栈(Python / Go / Node / PHP 等)通过 HTTP 调用。1.1.6 起提供,不包含在officia-all里,单独部署。
Java 项目直接引 officia-all 调门面即可,不需要它;它面向的是不想把 Officia 嵌进自己进程、 或者调用方不是 Java 的场景。
启动
java -jar officia-server-1.1.6-all.jar # 默认监听 8080启动后控制台会提示是否启用了令牌鉴权。未设置 OFFICIA_TOKEN 时接口不鉴权,切勿直接暴露到公网。
Docker
docker build -t officia-server . # 在 jar 所在目录,使用随附的 Dockerfile
docker run -d -p 8080:8080 \
-e OFFICIA_TOKEN=换成随机长串 \
-v /path/officia.lic:/app/officia.lic \
-v /path/fonts:/fonts \
officia-server- 镜像基于
eclipse-temurin:17-jre,内置 Noto CJK 与文泉驿正黑作回退字体;公文、发票常用的仿宋 / 楷体等 请把你方有授权的字体挂载到/fonts;转出后哪些字被替换了,可用 字体替换诊断 核对 officia.lic挂载到/app/officia.lic(工作目录约定位置),启动即自动加载;不挂载即为评估版- 镜像以非 root 用户(uid 10001)运行,挂载的授权文件与字体目录需对它可读
- 堆默认取容器内存的 75%(
-XX:MaxRAMPercentage=75),可用JAVA_OPTS整体覆盖 - 自带
HEALTHCHECK(GET /health),docker ps可直接看到健康状态;docker stop时服务会优雅退出
接口
除 /health 外一律 POST。请求体可以是文件原始字节,也可以是 multipart/form-data(取第一个文件字段)。
| 接口 | 说明 | 返回 |
|---|---|---|
GET /health | 健康检查 + 授权态 | {"status":"UP","inFlight":0,"licensed":true,"evaluation":false,"modules":["ofd","words"]} |
POST /api/words/pdf | Word(docx / doc 自动识别)→ PDF | application/pdf |
POST /api/words/ofd | Word → OFD | application/ofd |
POST /api/ofd/pdf | OFD → PDF | application/pdf |
POST /api/ofd/text | OFD → 文本(页间以 \f 分隔) | text/plain |
POST /api/ofd/invoice | OFD 电子发票 → 结构化数据 | JSON |
POST /api/ofd/verify | OFD 签章验证 | JSON |
POST /api/pdf/text | PDF → 文本 | text/plain |
POST /api/pdf/word | PDF → 可编辑 docx | docx |
TOKEN=你设置的令牌
# 原始字节
curl -H "Authorization: Bearer $TOKEN" --data-binary @a.docx http://host:8080/api/words/ofd -o a.ofd
# multipart
curl -H "Authorization: Bearer $TOKEN" -F file=@invoice.ofd http://host:8080/api/ofd/invoice/api/ofd/invoice 返回的字段与 OfdInvoice 一一对应 (invoiceNumber、issueDate、sellerName、totalAmount……),明细在 items,原始字段在 raw; evaluation 为 true 时关键值带 * 遮盖,切勿入账; /api/ofd/verify 返回 signed、valid、summary 与逐个签章的 signatures。
配置
环境变量或同名 -D 系统属性均可:
| 配置 | 默认 | 说明 |
|---|---|---|
OFFICIA_PORT | 8080 | 监听端口 |
OFFICIA_THREADS | CPU 核数 × 2 | 工作线程数 |
OFFICIA_MAX_MB | 50 | 单次上传上限(MB);超过 2047 按 2047 处理 |
OFFICIA_TOKEN | 无 | 设置后要求请求头 Authorization: Bearer <令牌>;不设则不鉴权 |
OFFICIA_FONT_DIR | 无(镜像内为 /fonts) | 追加字体目录 |
OFFICIA_MAX_REQ_SECONDS | 120 | 从收到请求到开始回响应的最长时间(含上传与转换),超时断开;大文档转换慢时调大 |
OFFICIA_MAX_RSP_SECONDS | 300 | 回写响应的最长时间 |
OFFICIA_TIMEOUT_SECONDS | OFFICIA_MAX_REQ_SECONDS − 10(默认 110) | 单次转换的期限,超时回 504。作用于 Word → PDF / OFD 与 OFD → PDF;文本抽取、发票解析、验签、PDF 转 Word 不受它约束。比连接期限短,转换会先停下并回明确的超时响应,而不是连接被断开后转换仍在后台空跑 |
授权文件按 Officia 的约定自动加载(工作目录的 officia.lic、-Dofficia.license、环境变量 OFFICIA_LICENSE 等), 详见 授权与加载。
错误码
| 状态码 | 含义 |
|---|---|
400 | 请求本身不合法:Content-Length 非法、multipart 缺 boundary 或找不到文件部分 |
401 | 缺少或错误的 Authorization: Bearer 令牌 |
404 | 未知接口 |
405 | 方法不对(除 /health 外只接受 POST) |
413 | 超过 OFFICIA_MAX_MB |
422 | 文档无法处理(损坏、加密、格式不支持等),返回 {"error":"..."},消息可直接展示给用户 |
504 | 转换超过 OFFICIA_TIMEOUT_SECONDS;文档本身未必有问题,可放宽期限或拆分后重试 |
500 | 内部错误:只返回事件号(如 内部错误,事件号 lz3k9a-1),不带内部细节;按事件号在服务日志里查堆栈 |
评估版
未加载授权时,各接口的行为与对应门面一致:转 PDF / OFD 限 30 页并带评估水印, OFD 文本只返回前 30 页(发票文字中的关键值遮盖),发票解析关键值部分遮盖。验签不受限。详见各模块页的「评估版限制」。
授权是否生效,看 /health 即可,不必拿文档试转:
| 字段 | 含义 |
|---|---|
licensed | 是否加载了有效授权 |
evaluation | 当前是否按评估版降级(未授权时为 true) |
modules | 授权覆盖的模块码(如 words、ofd;total 表示全部) |
出于安全考虑,/health 不返回被授权方名称与到期日。服务以评估态启动时,日志会打一条 WARNING 提示授权文件的放置位置。
生产部署建议
- 务必设置
OFFICIA_TOKEN,并放在内网或网关之后;未设置时启动日志会打一条 WARNING。服务本身不做限流 - 内存按「并发数 × 单份文档峰值」估算,大文档建议降低
OFFICIA_THREADS而不是只加堆 - 客户端中途断开的请求在访问日志里记为
499,便于和真正成功的200区分