Skip to content

7.1 文件上传全流程 ​

概述

上传采用两段式:先传临时目录(temp),表单提交保存时才转正到模块正式目录。未落库的临时文件不对外暴露,杜绝"传了不保存"的孤儿文件被枚举。

两段式流程 ​

text
① 上传接口(POST,multipart)
   upload.SaveTemp → {upload_dir}/temp/{yyyymmdd}/{32位随机}.{ext}
   返回访问 URL(前端表单持有)

② 保存记录(Add/Update)
   ModuleSpec FileFields 声明 → saveTransform
   upload.SaveFromTemp → {upload_dir}/{模块目录}/{yyyymmdd}/{时分秒_随机}.{ext}
   入库的是相对 uploadDir 的路径(不含 upload 段)

③ 读侧
   readTransform 补访问域名 → 完整 URL 返回前端

多文件字段走 SaveFromTempMulti(逗号分隔逐段转正)。

未转正的临时文件由每日 03:30 的清理任务(cmd/api 启动序列注册)按 file.tempExpireDays(默认 7 天)清理 temp/{日期} 目录——"传了不保存"的中间文件不会永久滞留。

物理路径契约 ​

text
临时:{upload_dir}/temp/{yyyymmdd}/{32位随机}.{ext}
正式:{upload_dir}/{正式子目录}/{yyyymmdd}/{时分秒_随机}.{ext}
入库:相对 uploadDir 的路径(不含 upload 段)
访问:file.domainUrl + "/" + 入库路径(nginx 直供)

核心 API(utility/upload) ​

函数说明
SaveTemp(ctx, fileHeader, typ)两段式第一段:落临时目录
SaveFromTemp(ctx, fileUrl, saveDir)第二段:转正到模块目录
SaveFromTempMulti多文件版本
GetFileUrl(ctx, path)相对路径 → 访问 URL
SafeJoin(base, rel)路径穿越防护(清洗后必须仍在基目录内)
BaseDir / TempBaseDir / GetAccessBase目录基址查询

安全设计 ​

防护实现
扩展名白名单imageExt / fileExt 配置(服务端校验)
内容嗅探图片类校验真实文件头(isImage)
大小限制file.maxSize(应用)+ client_max_body_size(nginx)对齐
路径穿越SafeJoin 断言
temp 枚举nginx 与应用开发回退均封禁 /temp/
SVG 风险nginx 强制附件下载 + nosniff

与 dto 的配合 ​

文件上传字段用 *multipart.FileHeader + UnmarshalBody 逃生舱解析(见 3.3 契约层开发)。

下一步 ​

→ 7.2 上传配置详解

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