96 lines
3.1 KiB
Markdown
96 lines
3.1 KiB
Markdown
# 8.4 文件上传接口
|
||
|
||
:::tip 概述
|
||
上传接口统一 multipart:POST /api/upload/uploadFile(单文件)与 uploadFiles(多文件),字段名 file。返回可预览 URL 与入库形态 Path。两段式协议详见 [7.1 文件上传全流程](../tools/upload)。
|
||
:::
|
||
|
||
## 接口定义
|
||
|
||
```text
|
||
POST /api/upload/uploadFile 权限 sys:upload:file multipart 字段名 file
|
||
POST /api/upload/uploadFiles 权限 sys:upload:files 多文件
|
||
|
||
入参 type=image 时按图片规则校验(扩展名 + 魔数嗅探),否则按普通文件
|
||
```
|
||
|
||
multipart 标签约定:`*ghttp.UploadFile` + `p:"file"`。
|
||
|
||
## 请求示例
|
||
|
||
```sh
|
||
curl -X POST http://127.0.0.1:8000/api/upload/uploadFile \
|
||
-H "Authorization: Bearer <access_token>" \
|
||
-F "file=@avatar.png" \
|
||
-F "type=image"
|
||
```
|
||
|
||
## 响应结构
|
||
|
||
```json
|
||
{
|
||
"code": 0, "ok": true, "msg": "操作成功",
|
||
"data": {
|
||
"originalName": "avatar.png",
|
||
"fileExtension": "png",
|
||
"fileType": "image/png",
|
||
"fileSize": 102400,
|
||
"fileName": "a1b2c3....png",
|
||
"filePath": "temp/20261018/a1b2c3....png",
|
||
"fileUrl": "http://file.example.com/temp/20261018/a1b2c3....png"
|
||
}
|
||
}
|
||
```
|
||
|
||
| 字段 | 用途 |
|
||
|------|------|
|
||
| originalName | 原始文件名(前端展示/回显用) |
|
||
| fileExtension | 扩展名(小写,无点) |
|
||
| fileType | MIME 类型(按文件头内容嗅探,识别不出为 application/octet-stream) |
|
||
| fileSize | 文件大小(字节) |
|
||
| fileName | 存储文件名(= filePath 的 basename,32位随机.ext) |
|
||
| filePath | 相对 uploadDir 路径(**入库形态**;表单保存时转正) |
|
||
| fileUrl | 可直接预览的完整地址(domainUrl 拼接) |
|
||
|
||
## 校验失败场景
|
||
|
||
| 场景 | 响应 |
|
||
|------|------|
|
||
| 超过 maxSize(默认 10MB) | code=1,msg 提示大小超限 |
|
||
| 扩展名不在白名单 | code=1,msg 提示类型不允许 |
|
||
| type=image 但魔数非 image/* | code=1,拒绝(防改后缀伪造) |
|
||
| 未登录/令牌无效 | code=401 |
|
||
| 无权限 | code=403 |
|
||
| 触发限流 | code=429 |
|
||
|
||
## 两段式协议(对接要点)
|
||
|
||
```text
|
||
上传阶段:只落 temp 目录(upload/temp/日期/随机名)
|
||
前端持有 url;表单字段存 url 或 path
|
||
|
||
保存阶段:业务接口(userAdd/articleAdd/...)的 spec.saveTransform
|
||
自动 SaveFromTemp 转正到业务目录(user/日期/时间戳_随机.ext)
|
||
库存相对路径
|
||
|
||
读取阶段:Detail/List 的 readTransform 经 GetFileUrl 补域名
|
||
```
|
||
|
||
前端不要在上传后直接把 url 当最终地址持久化到业务表——转正由业务保存触发。
|
||
|
||
## 批量上传(uploadFiles)
|
||
|
||
```text
|
||
POST /api/upload/uploadFiles
|
||
multipart 多个 file 字段 → 逐个 SaveTemp → 返回结果数组
|
||
(每项同单文件结构;单项校验失败不影响其他项——对照导入的逐行语义)
|
||
```
|
||
|
||
## 安全链速查
|
||
|
||
```text
|
||
大小限制 → 扩展名白名单 → 图片魔数嗅探 → 随机文件名 → 两段式
|
||
→ svg 附件化+nosniff → temp 定期清理(tempExpireDays + 03:30 gcron)
|
||
```
|
||
|
||
公网开放上传时收紧 fileExt(当前含 js/css/sql)——配置见 [7.2 上传配置详解](../tools/upload-config)。
|