使用fasthttp POST提交multipart/form-data遇unexpected EOF错误求助
multipart/form-data 请求异常:unexpected EOF 问题修复
错误原因
核心问题是multipart.Writer.Close()的调用时机错误。multipart.Writer在关闭时会自动写入multipart请求的结束边界分隔符,原代码中先将bodyBuffer的内容设置到请求,之后才关闭writer,导致请求体缺少了这个关键的结束标记,服务器解析时因数据不完整抛出unexpected EOF。另外,writeFilesData中打开的文件未关闭,存在资源泄漏风险。
修复方案
- 调整
bodyWriter.Close()的执行顺序:在写完所有字段和文件后,立即关闭writer,确保bodyBuffer包含完整的multipart数据(包括结束边界)。 - 关闭writer后,再将
bodyBuffer的内容设置到请求体中。 - 在
writeFilesData中添加文件关闭逻辑,使用defer file.Close()确保文件资源被释放。
修复后的完整代码
type FastHttpRestClient struct { client *fasthttp.Client } func (c *FastHttpRestClient) PostForm(request Request) ([]byte, error) { bodyBuffer := &bytes.Buffer{} bodyWriter := multipart.NewWriter(bodyBuffer) req := fasthttp.AcquireRequest() defer fasthttp.ReleaseRequest(req) // 设置请求头 if request.Headers != nil { for k, v := range request.Headers { req.Header.Set(k, v) } } // 添加表单字段 if request.FormData != nil { err := writeFieldsData(bodyWriter, request.FormData) if err != nil { return nil, err } } // 添加文件字段 if request.FileFields != nil { err := writeFilesData(bodyWriter, request.FileFields) if err != nil { return nil, err } } // 关键修复:先关闭writer,确保写入结束边界 err := bodyWriter.Close() if err != nil { return nil, err } // 设置请求信息 req.Header.SetMethod(fasthttp.MethodPost) req.SetRequestURI(request.URL) req.SetBody(bodyBuffer.Bytes()) req.Header.Set("Content-Type", bodyWriter.FormDataContentType()) resp := fasthttp.AcquireResponse() defer fasthttp.ReleaseResponse(resp) if err := c.client.Do(req, resp); err != nil { return nil, err } return resp.Body(), nil } func writeFieldsData(bodyWriter *multipart.Writer, fields map[string]string) error { for k, v := range fields { fieldWriter, err := bodyWriter.CreateFormField(k) if err != nil { return err } _, err = fieldWriter.Write([]byte(v)) if err != nil { return err } } return nil } func writeFilesData(bodyWriter *multipart.Writer, fileFields map[string][]*multipart.FileHeader) error { for fieldName, fileHeaders := range fileFields { for _, fileHeader := range fileHeaders { fileWriter, err := bodyWriter.CreateFormFile(fieldName, fileHeader.Filename) if err != nil { return err } file, err := fileHeader.Open() if err != nil { return err } // 修复:添加defer确保文件关闭 defer file.Close() _, err = io.Copy(fileWriter, file) if err != nil { return err } } } return nil }
关键修改点说明
- 将
bodyWriter.Close()移到了写入所有字段和文件之后、设置请求体之前,确保bodyBuffer包含完整的multipart数据。 - 在
writeFilesData中为打开的文件添加了defer file.Close(),避免文件资源泄漏。
内容的提问来源于stack exchange,提问作者Tuna Non
相关产品推荐
相关产品推荐

