如何修改Go语言文件发送函数,替换application/octet-stream为正确Content-Type
解决Go语言文件上传时Content-Type被设为application/octet-stream的问题
原代码核心问题
- 重复请求逻辑:循环内同时通过
multipart.Writer构建批量文件请求,又调用sendFileToURL单独发送每个文件,逻辑冗余且冲突 CreateFormFile的默认行为:该方法会强制将文件部分的Content-Type设为application/octet-stream,覆盖原文件的头部信息- 错误的单文件上传方式:
sendFileToURL直接将文件内容作为POST请求体发送,未封装为标准的multipart/form-data格式,不符合常规文件上传接口的解析要求
修正后的代码
func (s *FileService) SentFileToCreate(ctx context.Context, userUUID string, form *multipart.Form) (*models.File, error) { var fileResult = &models.File{} now := time.Now() textValue := form.Value["text"][0] files := form.File["files"] id, _ := s.repo.GetUserIdByUuid(ctx, userUUID) fileResult.Text = textValue fileResult.CreatedStamp = &now fileResult.AuthorID = id var mediaL []*models.File body := &bytes.Buffer{} writer := multipart.NewWriter(body) defer writer.Close() url := "http://0.0.0.0:9090/api/v1/file/upload" // 添加text字段到multipart表单 if err := writer.WriteField("text", textValue); err != nil { return nil, err } for _, file := range files { media := &models.File{ FileName: file.Filename, ContentType: file.Header.Get("Content-Type"), } mediaL = append(mediaL, media) // 手动构建文件部分的MIME头部,保留原Content-Type partHeader := make(textproto.MIMEHeader) partHeader.Set("Content-Disposition", fmt.Sprintf(`form-data; name="files"; filename="%s"`, file.Filename)) partHeader.Set("Content-Type", file.Header.Get("Content-Type")) part, err := writer.CreatePart(partHeader) if err != nil { return nil, err } fileContent, err := file.Open() if err != nil { return nil, err } _, err = io.Copy(part, fileContent) fileContent.Close() // 避免defer在循环内累积导致资源泄漏 if err != nil { return nil, err } } req, err := http.NewRequest("POST", url, body) if err != nil { return nil, err } // 设置正确的multipart表单Content-Type,包含boundary req.Header.Set("Content-Type", writer.FormDataContentType()) client := &http.Client{} resp, err := client.Do(req) if err != nil { return nil, err } defer resp.Body.Close() fmt.Println("Status:", resp.Status) return s.repo.SaveFile(ctx, fileResult) } // 移除原sendFileToURL函数,因为已统一用multipart.Writer处理上传逻辑
关键修改说明
- 移除冗余的
sendFileToURL:统一通过multipart.Writer构建包含所有字段和文件的完整请求体,避免重复请求 - 手动创建表单文件部分:用
writer.CreatePart替代CreateFormFile,手动设置Content-Disposition和原文件的Content-Type,确保接收端能识别正确的文件类型 - 修复资源泄漏:循环内打开文件后立即关闭,避免
defer在循环中累积导致大量文件句柄未及时释放 - 添加text字段到表单:原代码中只处理了文件,但未将
text字段加入到最终发送的multipart表单中,补充该逻辑保证请求参数完整
内容的提问来源于stack exchange,提问作者Piter Penn
相关产品推荐
相关产品推荐

