Skip to content

7.3 富文本处理 ​

概述

富文本的核心是 [IMG_URL] 持久化契约:存库时本站图片引用转为占位符(LocalizeContentFields),读取时还原为访问基址(ExpandContentFields,唯一还原出口)。content 字段的库内格式是系统私有契约。

转换流图 ​

text
写侧 LocalizeContentFields(content, saveDir):
  正文 HTML
    │ 正则提取 img/video/source/embed[src] + a[href(带后缀)]
    │ 逐 URL 判断:
    │   含 /temp/      → SaveFromTemp 转正 → "[IMG_URL]/user/.../x.png"
    │   本站正式路径    → 剥离 domainUrl   → "[IMG_URL]/user/.../x.png"
    │   外站 http(s)   → 跳过(不处理,规避 SSRF)
    ▼
  库存 content(含 [IMG_URL] 占位符;此为持久化格式契约)

读侧 ExpandContentFields(content):
  "[IMG_URL]" ──ReplaceAll──▶ 访问基址(GetAccessBase)──▶ 前端富文本展示
  唯一还原出口;ModuleSpec.ContentFields 声明后两侧自动接入

契约要点 ​

[IMG_URL] 是持久化契约

  1. [IMG_URL] 是库内 content 字段格式的一部分——content 不供第三方系统直接消费
  2. 还原只能走 ExpandContentFields——业务代码禁止手写字符串替换
  3. 读取必须走 Detail/List(基座 ContentFields 自动 Expand)——直接 Struct 输出会漏还原
  4. 外站 URL 不本地化不替换(设计边界:防 SSRF 与外链下载)

声明式接入(ModuleSpec) ​

go
ContentFields: []string{"content"},   // 读写两侧自动接入
FileSaveDir:   "article",             // 内嵌 temp 图片的转正目录

接入后基座自动完成:

text
写侧(Add/Update → saveTransform):
  LocalizeContentFields 处理 content(temp 图片转正 + 占位符化)
读侧(Page/Detail → readTransform):
  ExpandContentFields 还原占位符为访问基址

article.content 是典型接入字段;未接入 ContentFields 的模块需手动调 base.go 两个函数(不推荐)。

匹配范围(写侧正则) ​

text
img[src] / video[src] / source[src] / embed[src]
a[href](仅带文件后缀的链接——普通网页链接不处理)

普通 <a href="https://example.com"> 外链保持原样(是超链接不是资源引用)。

前端协作 ​

text
编辑器(TinyMCE/Quill):
  上传图片走 /api/upload/uploadFile → 得到 temp URL → 插入编辑器
  编辑器内容即正文 HTML(含 temp URL)

保存:正文提交 → 后端 LocalizeContentFields 转正+占位符化 → 入库
回显:Detail 返回已还原的完整 URL → 编辑器直接渲染
再次编辑:取 Detail 内容 → 编辑 → 保存(循环;已正式的图片引用保持稳定)

排障 ​

症状原因
富文本图片不显示读取绕过了基座(直接 Struct);或 domainUrl 配置错(还原基址不对)
库里看到 [IMG_URL]正常——库内契约格式;接口输出应已还原
外站图片 404外站 URL 不本地化是设计边界;如需本地化要另行开发(注意 SSRF 防护)
图片重复转正正式路径引用幂等(归一化原样返回),不会重复移动;temp 引用每次编辑会重新转正(保存前应已在阶段一转正)
第三方系统读 content 乱码content 是私有契约——第三方消费应走 Detail 接口(已还原)而非直读库

小蚂蚁云团队 · 提供技术支持