Go开发HTTP REST API如何通过单个POST请求上传带关联ID的多文件
最优通用解决方案
最通用且性能最优的方案是继续使用multipart/form-data格式承载请求,通过约定表单字段的规则实现文件与ID的关联,有两种落地方式可选:
方案1:表单字段名绑定ID(最推荐)
前端上传时将每个文件对应的表单name属性设置为file:<关联ID>的格式,例如file:1001、file:user_avatar_987,后端直接拆分字段名即可拿到每个文件对应的ID,无需额外处理其他字段,实现最简单。
改造后的示例代码如下:
import "strings" func handlePut(w http.ResponseWriter, r *http.Request) { if r.Method != http.MethodPost { fmt.Fprintln(w, errorf("invalid request, expected POST got %s", r.Method)) return } // 注意捕获ParseMultipartForm的返回错误 err := r.ParseMultipartForm(1 << 20) // 1Mb内存缓存,超出部分落盘 if err != nil { fmt.Fprintln(w, errorf("parse form failed: %v", err)) return } if r.MultipartForm == nil || len(r.MultipartForm.File) == 0 { fmt.Fprintln(w, errorf("no file provided")) return } // 遍历所有文件字段 for fieldName, headers := range r.MultipartForm.File { // 拆分字段名获取关联ID,这里约定前缀是file: idParts := strings.SplitN(fieldName, ":", 2) if len(idParts) != 2 || idParts[0] != "file" { continue // 跳过不符合规则的字段 } fileID := idParts[1] for _, h := range headers { tmp, err := h.Open() if err != nil { log.Println("handlePut", "h.Open", err) continue } fname := filepath.Base(h.Filename) cnt, err := io.ReadAll(tmp) tmp.Close() // 这里可以直接使用拿到的fileID和文件内容、文件名做业务处理 // do something with fileID, cnt and fname } } fmt.Fprintln(w, "upload success") }
方案2:额外传递ID映射字段
如果你的业务场景不允许修改文件对应的表单字段名,可以让前端额外传一个名为file_id_map的表单字段,值为JSON格式的映射关系,示例值为{"report.pdf":"1001","avatar.png":"1002"},后端先读取这个映射字段,再匹配拿到的文件名即可获取对应ID。
可选补充方案(仅适合小文件场景)
如果所有上传文件都是小于1Mb的小文件,也可以要求前端将文件转为Base64编码,放在JSON数组中提交,数组每个元素包含id、file_name、content三个字段即可,这种方式解析逻辑简单,但会增加约33%的传输体积,大文件场景不推荐使用。
内容的提问来源于stack exchange,提问作者NicoNex
相关产品推荐
相关产品推荐

