package starnet import ( "context" "io" "mime/multipart" "os" ) // applyMultipartBody 应用 multipart 请求体 func (r *Request) applyMultipartBody(execCtx context.Context) error { pr, pw := io.Pipe() writer := multipart.NewWriter(pw) r.httpReq.Header.Set("Content-Type", writer.FormDataContentType()) r.httpReq.Body = pr go func() { defer pw.Close() defer writer.Close() for key, values := range r.config.Body.FormData { for _, value := range values { if err := writer.WriteField(key, value); err != nil { pw.CloseWithError(wrapError(err, "write form field")) return } } } for _, file := range r.config.Body.Files { if err := r.writeFile(execCtx, writer, file); err != nil { pw.CloseWithError(err) return } } }() return nil } // writeFile 写入文件到 multipart writer func (r *Request) writeFile(execCtx context.Context, writer *multipart.Writer, file RequestFile) error { part, err := writer.CreateFormFile(file.FormName, file.FileName) if err != nil { return wrapError(err, "create form file") } var reader io.Reader if file.FileData != nil { reader = file.FileData } else if file.FilePath != "" { f, err := os.Open(file.FilePath) if err != nil { return wrapError(err, "open file") } defer f.Close() reader = f } else { return ErrNilReader } _, err = copyWithProgress(execCtx, part, reader, file.FileName, file.FileSize, r.config.UploadProgress) if err != nil { return wrapError(err, "copy file data") } return nil }