Docs 多格式转换与 .docx 导入:Y-Provider 转换服务与 DocSpec 配置实战指南
【免费下载链接】docsDocs is an open-source text editor: web-native, made for real-time collaboration, cleanly structured documents and sub-documents with full ownership of your data. Built to scale with Django and React.项目地址: https://gitcode.com/GitHub_Trending/docs150/docs
本文档是 Docs 项目(Django + React 构建的 Web 原生实时协作文本编辑器)中「格式转换」模块的技术指南,覆盖从 Markdown / HTML / JSON 导出到 .docx 导入的完整配置链路。读完本文,你将掌握formatted-content端点的用法、Y-Provider 转换服务的环境变量配置与源码调用链、Kubernetes Helm 部署下拆分 WebSocket 与转换服务的方案,以及 DocSpec 服务的启用与安全部署建议。
一、格式转换能力总览
Docs 允许以多种格式操作文档内容:
- 导出为 HTML、Markdown、JSON 等格式;
- 以 Markdown 复制、粘贴与导入;
- 在启用 DocSpec 服务后,支持导入
.docx文件并转换为 Docs 内部的 Yjs 文档格式。
这一切由两个外部服务支撑:
| 服务 | 职责 | 备注 |
|---|---|---|
| Y-Provider(y-provider) | 核心转换引擎:在 Markdown / HTML / JSON / Yjs / BlockNote 之间互相转换,同时承载实时协作 WebSocket | 同一服务可拆分部署 |
| DocSpec | 将 legacy 格式(如.docx)转换为现代编辑器可用的 BlockNote 内容 | 独立部署,需自行托管 |
转换链路并非只有文档中明示的配置项,还涉及 Django 端的环境变量、y-provider 端的 API 路由与认证机制,下面逐层展开。
二、转换配置:Django 与 Y-Provider 的环境变量
2.1 Django 侧:指向 Y-Provider 转换 API
在 Django 服务中配置以下两个环境变量,即可启用转换能力:
Y_PROVIDER_API_BASE_URL: http://{y-provider-service}:443/api/ Y_PROVIDER_API_KEY: a-shared-private-key-with-y-provider其中:
Y_PROVIDER_API_BASE_URL:y-provider 转换 API 的基地址。可以指向你通过反向代理暴露的 Docs 实例 FQDN(需为 y-provider 的/api路由配置代理),也可以直接使用 y-provider 内部服务地址。若部署在 Kubernetes 集群中,可使用 y-provider 的 Service 名称(官方更推荐内部 URL)。Y_PROVIDER_API_KEY:与 y-provider 共享的私有密钥,用于服务间认证。
在 settings.py 中,这两个值被声明为 Django-environ 变量:Y_PROVIDER_API_KEY使用SecretFileValue(支持从文件读取密钥),Y_PROVIDER_API_BASE_URL使用普通Value,两者environ_prefix=None,意味着环境变量名与属性名完全一致。
2.2 y-provider 侧:共享同一个 API Key
y-provider 也必须配置相同的密钥:
Y_PROVIDER_API_KEY: a-shared-private-key-with-y-provider在 env.ts 中,y-provider 通过Y_PROVIDER_API_KEY_FILE(优先)或Y_PROVIDER_API_KEY环境变量读取该密钥。认证校验位于 middlewares.ts:服务维护VALID_API_KEYS列表(包含协作服务器密钥与转换 API 密钥),并校验请求头authorization是否在其中。
注意:根据 converter_services.py 的实现,Django 端实际发送的是
Bearer {Y_PROVIDER_API_KEY}形式;注释也特别提醒:y-provider 微服务只接受裸 token(raw token),这并非推荐做法,仅作为当前实现的事实说明。
2.3 formatted-content 端点:配置好之后的调用入口
完成上述配置后,即可使用formatted-content端点获取文档的多格式内容:
GET /api/v1.0/documents/{document_id}/formatted-content/?content_format=(json|html|markdown)该端点由 viewsets.py 中的formatted_contentaction 实现:
- 通过
content_format查询参数指定输出格式,缺省为json;仅接受json、markdown、html三种取值,否则返回 400; - 从文档对象中取出 Base64 编码的 Yjs 内容,
base64.b64decode解码; - 调用
Converter服务,将mime_types.YJS转换为目标格式; - 转换失败时按异常类型返回 400(验证失败)或 500(服务不可用)。
同一转换服务还被create-for-owner端点以及 Markdown 文件导入流程复用。
三、转换调用链的源码级解析
3.1 Converter 编排器
Django 侧的转换入口是 converter_services.py 中的Converter类,它内部组合了两个专用转换器:
DocSpecConverter:处理.docx→ BlockNote 的转换;YdocConverter:处理 Markdown / Yjs / HTML / JSON 等格式间的转换。
convert(data, content_type, accept)的编排逻辑为:
if content_type == mime_types.DOCX and accept == mime_types.YJS: blocknote_data = self.docspec.convert(data, content_type, mime_types.BLOCKNOTE) return self.ydoc.convert(blocknote_data, mime_types.BLOCKNOTE, mime_types.YJS) return self.ydoc.convert(data, content_type, accept)也就是说,.docx导入实际是两段式转换:先由 DocSpec 转成 BlockNote JSON,再由 y-provider 把 BlockNote 转成 Docs 内部的 Yjs 文档,从而让用户享受到 Docs 全部编辑能力而无需受 legacy 格式限制。
3.2 YdocConverter 与 y-provider 的 convert 端点
YdocConverter._request以POST方式请求{Y_PROVIDER_API_BASE_URL}{CONVERSION_API_ENDPOINT}/(端点默认值为convert,见 settings.py),携带Authorization、Content-Type、Accept三个请求头,并受CONVERSION_API_TIMEOUT(默认 30 秒)与CONVERSION_API_SECURE(默认 False)控制。
y-provider 侧对应的处理逻辑位于 convertHandler.ts,路由定义为CONVERT: '/api/convert/'(见 routes.ts)。其支持的输入输出矩阵如下:
| 方向 | Content-Type(输入) | Accept(输出) | 说明 |
|---|---|---|---|
| 读取 | text/markdown、text/x-markdown、application/x-www-form-urlencoded | — | 后者为向后兼容,按 Markdown 解析 |
| 读取 | application/vnd.yjs.doc、application/octet-stream | — | Yjs 二进制更新 |
| 读取 | application/vnd.blocknote+json | — | BlockNote JSON |
| 写出 | — | application/vnd.blocknote+json、application/json | 返回 blocks |
| 写出 | — | application/vnd.yjs.doc、application/octet-stream | 编码为 Yjs state update |
| 写出 | — | text/markdown、text/x-markdown | blocksToMarkdownLossy(有损) |
| 写出 | — | text/html | blocksToHTMLLossy(有损) |
转换基于服务端ServerBlockNoteEditor(BlockNote 的服务器端编辑器),并将CommentsExtension注册进 schema,以保留评论标记(mark)在转换中的完整性——若缺少该扩展,被评论包裹的文本在转换时会被静默丢弃,导致相关块变空。
在YdocConverter.convert的返回处理中(converter_services.py):
- 输出为 Yjs 时,将二进制响应
base64编码后返回字符串; - 输出为 Markdown / HTML 时,返回文本;
- 输出为 JSON 时,解析为对象返回。
3.3 异常与错误语义
转换模块定义了三个异常类型(converter_services.py):
ConversionError:基类;ValidationError:输入校验失败(空数据、不支持的格式组合),对应 400;ServiceUnavailableError:无法连接转换服务或请求异常,对应 500。
y-provider 侧则按 HTTP 语义返回:请求体为空返回 400、不支持的 Content-Type 返回 415、不支持的 Accept 返回 406、内容解析失败返回 400、服务端异常返回 500,并将错误上报 Sentry。
四、拆分转换服务:WebSocket 与 Converter 分而治之
转换服务与 WebSocket 服务同属于 y-provider 服务器。当转换负载较重时,可以将二者拆分部署:一份 y-provider 专用于 WebSocket,另一份专用于转换。
该能力目前仅在官方 Helm Chart 中提供;若使用其他部署方式,可参考其实现自行落地。
4.1 Helm 中一键启用
在 Helm values 中启用即可:
yProvider: converter: enabled: trueyProvider.converter下的所有参数都可以覆盖yProvider下的同名参数(values.yaml 中可看到 replicas、resources、service.port、command、args、sidecars、persistence、pdb 等完整可覆盖项),Chart 会为此单独生成yprovider_deployment_converter.yaml与yprovider_svc_converter.yaml(见 helm/impress/templates 目录)。
4.2 更新 Django 的 Y_PROVIDER_API_BASE_URL
启用拆分后,Django 需要指向新生成的转换服务,其命名规则是在原服务名后追加-converter:
拆分前:
Y_PROVIDER_API_BASE_URL: http://impress-docs-y-provider:443/api/拆分后:
Y_PROVIDER_API_BASE_URL: http://impress-docs-y-provider-converter:443/api/五、DocSpec 配置:启用 .docx 导入
5.1 DocSpec 是什么
DocSpec 是一个外部服务,负责把 legacy 文档格式转换为现代编辑器可访问、可复用的内容。Docs 使用它将.docx文件转换为 BlockNote 内容后接入 Docs 编辑体系,从而获得 Docs 的全部能力而规避 legacy 格式的限制。
DocSpec 需要自行部署。若使用官方 Helm Chart,只需在 values 中启用:
docSpec: enabled: truevalues.yaml 中提供了docSpec的完整配置项:镜像仓库(默认ghcr.io/docspecio/api)、replicas、command/args、envVars、service.port、探针路径、resources、nodeSelector、tolerations、extraVolumes 等。
5.2 安全部署注意事项
DocSpec 暴露的是公开 API——任何知道其 URL 的人都可以调用。因此官方强烈建议将其部署在私有网络中,仅允许 Docs 后端访问,切勿直接暴露到公网。
5.3 Django 侧启用 DocSpec
DocSpec 部署完成后,在 Django 中配置以下环境变量开启 .docx 导入:
CONVERSION_UPLOAD_ENABLED: True DOCSPEC_API_URL: http://impress-docs-docspec:4000/conversionCONVERSION_UPLOAD_ENABLED:是否允许上传文件并转换,默认False(见 settings.py);DOCSPEC_API_URL:DocSpec 转换接口地址。DocSpecConverter会向该地址发送POST请求,请求头为Content-Type: 源格式、Accept: application/vnd.blocknote+json(见 converter_services.py)。
六、导入相关的进阶配置项
除上述核心变量外,settings.py 还暴露了一组与文件导入相关的可调参数,供生产环境按需调整:
| 环境变量 | 默认值 | 说明 |
|---|---|---|
CONVERSION_FILE_MAX_SIZE | DATA_UPLOAD_MAX_MEMORY_SIZE | 允许上传转换的文件大小上限(字节) |
CONVERSION_FILE_EXTENSIONS_ALLOWED | [".docx", ".md"] | 允许上传转换的文件扩展名白名单 |
CONVERSION_API_ENDPOINT | convert | 转换 API 路径段,拼接到Y_PROVIDER_API_BASE_URL之后 |
CONVERSION_API_CONTENT_FIELD | content | 转换请求中内容字段名 |
CONVERSION_API_TIMEOUT | 30 | 转换请求超时(秒) |
CONVERSION_API_SECURE | False | 转换请求是否校验 TLS 证书 |
注意:y-provider 侧还有独立的CONVERSION_FILE_MAX_SIZE(默认 20 MB,见 env.ts),上传文件时两侧限制都会生效,需确保二者匹配。
七、配置速查与典型部署形态
7.1 最小配置清单
仅启用 Markdown / HTML / JSON 多格式转换(无需 .docx 导入):
# Django Y_PROVIDER_API_BASE_URL: http://{y-provider-service}:443/api/ Y_PROVIDER_API_KEY: a-shared-private-key-with-y-provider # y-provider Y_PROVIDER_API_KEY: a-shared-private-key-with-y-provider启用 .docx 导入(追加):
# Django CONVERSION_UPLOAD_ENABLED: True DOCSPEC_API_URL: http://impress-docs-docspec:4000/conversion7.2 典型部署形态
- 单体形态:单一 y-provider 同时承担 WebSocket 与转换,适合小规模部署;
- 拆分形态:Helm 中启用
yProvider.converter.enabled,将转换负载隔离,适合转换频繁或大规模文档导入场景; - 私有化 DocSpec:DocSpec 仅部署于内网,由 Django 后端通过
DOCSPEC_API_URL调用,实现安全可控的 .docx 导入。
相关参考资源:
- 端点实现:viewsets.py
- 转换编排与异常:converter_services.py
- Django 环境变量定义:settings.py
- y-provider 转换处理:convertHandler.ts、routes.ts
- y-provider 环境变量与认证:env.ts、middlewares.ts
- Helm 配置:values.yaml、部署示例
- 转换服务测试:test_services_converter_services.py、convert.test.ts
【免费下载链接】docsDocs is an open-source text editor: web-native, made for real-time collaboration, cleanly structured documents and sub-documents with full ownership of your data. Built to scale with Django and React.项目地址: https://gitcode.com/GitHub_Trending/docs150/docs
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考