附件用编码内容通过接口上传时,体积和校验该注意什么
附件用 base64 编码内容通过接口上传时,要接受一个前提:传输的是文本,不是原始字节。体积会因此放大,估算是按「编码后放大约三分之一」这个口径来做,而不是按文件大小直接申请配额。站内自 v3.6.5 起在附件能力中支持以 base64 上传,主要面向没有表单交互的批量导入场景。校验则分三段做:提交前本地校验、请求体上限对齐、返回结果核对。
两种上传方式的适用场景
multipart 表单上传适合人工操作:浏览器直接读文件,请求体按二进制分块传输,体积接近文件本身。
base64 上传适合程序化调用:调用方已经把内容放在内存或配置里,比如从另一个系统导出数据后立刻入库、脚本批量补附件、把内容塞进 JSON 请求体一起发出去。它的代价是体积膨胀与内存占用,换来的是请求结构单一,不需要处理 multipart 的分块格式。
判断标准很简单:数据来源是「磁盘上的文件」就用表单,来源是「程序里的字符串」就用编码上传。两者混用时,同一批附件的体积会不一致,后期排查容易误判。
编码后体积为什么会变大,该按什么估
base64 把每三字节的原始数据编码成四个可打印字符,所以编码后的文本长度约为原始大小的三分之四,放大约三分之一。这是算法决定的固定比例,与文件类型、压缩状态无关。
实操上按三步估。
第一步,把原始大小换算成「编码后大小」,按放大三分之一来预留,再往上取整到便于核对的量级。第二步,把编码后的字符串放进 JSON 时再算一次开销:转义、字段名与外层结构都会增加字节,批量时这部分累积不小。第三步,按单次请求而不是按总任务量核对上限,因为限制通常作用在单个请求体上。
一个常见的错误做法是「文件不大就直接批进去」。真正决定成败的是单次请求的体积,一次带十个附件与分十次各带一个,触发的限制完全不同。
请求体上限要在哪几层对齐
请求从调用方走到应用,一般会穿过好几层,每层都可能有自己的体积限制。常见的四层是:调用方自身的读入与序列化限制、反向代理或 Web 服务器对请求体的限制、运行环境对单次请求体或内存的限制、应用层对附件字段与文件类型的校验。
对齐顺序建议自下而上:先确认应用接受什么类型与多大,再确认运行环境是否容得下这个体积,然后核对代理层是否会把更大的请求直接拒掉,最后调整调用方的分批策略。
判断在哪一层被拒,看返回形态比看错误文字更快。代理层直接拒绝时,往往连应用的日志都不会留下痕迹;应用层拒绝时,通常能读到明确的字段校验信息。排查时先确认请求是否到达了应用,可以省掉一半无效工作。
还有一点容易被忽略:编码上传会把整个内容放进内存,批量并发时内存峰值按「并发数乘以单个体积」累积。体积合适的单请求,在并发下未必合适。
导入接口与公开能力清单的分工
批量导入用文档内容导入接口 /api/import/archive,它支持 ZIP 压缩包与 Excel 表格这类批量形式,并且支持按标题查询内容是否已存在。后者在重试场景里很关键:网络中断或任务重跑时,先按标题确认再决定是否重新提交,比无条件重发更安全。
公开的能力清单负责另一件事。接口文档里描述的高频能力包括文档列表与详情、分类与标签、上传图片、留言与评论、友情链接、系统设置与联系方式,这些是可读或可写的公开操作面。它与导入接口的分工是:导入接口管「成批把内容放进来」,能力清单管「按结构取用与单点维护」。
上传图片与上传附件也不是一回事。前者服务于正文展示,后者服务于文档附带的文件;混用会让附件出现在图片列表里,或让配图无法被图片相关能力取到。
常见失败与判断顺序
按出现频率从高到低排:
请求被中间层直接拒掉,特征是应用无日志。处理方式是缩小单批体积或改走表单上传。
编码本身不完整,特征是解码后内容损坏,常见于换行与空格在传输或复制中被改动。处理方式是生成后立刻做一次解码自检。
类型与扩展名不一致,特征是应用侧拒绝或前台无法预览。处理方式是提交时显式声明类型,而不是让服务端猜。
重复导入,特征是同一标题出现多份。处理方式是用按标题查询的能力先做存在性判断。
内存峰值过高,特征是任务批量跑一段时间后变慢或失败。处理方式是串行化或限制并发,而不是继续提高上限。
常见问题
编码上传适合多大的文件? 没有固定阈值,按「编码后体积是否落在各层限制内」判断。体积较大的文件更适合作为外部存储引用,或走表单上传通道。
能否一次请求带多个附件? 取决于接口对请求体的定义。多数情况下按单附件提交更容易定位失败原因,也更利于重跑。
上传成功但前台读不到附件怎么查? 先确认返回结果里附件标识是否写入,再确认它挂在哪个文档状态下;草稿状态的文档下,附件可见性与正式文档不同。
要不要自己算校验和? 建议保留原始文件的校验信息,用于确认解码后与源文件一致。这一步在批量迁移里比事后发现损坏更省事。
接口路径可以直接写在正文里吗? 站内接口路径属于站内实现,可以在技术文档里出现;站外地址不写进内容正文,两者不要混。