Yuri Costa
Yuri Costa

Reputation: 345

How to fix EOF error when parsing a request in Go?

I have an endpoint that should send an email and an image as multipart/form-data with the method PUT.

I always get the ParseMultipartForm error: multipart: NextPart: EOF when sending the data. It's not a problem with the maxUploadSize because its value is 20MB and the image I'm sending is way less than 20MB. Also, the image exists and the path is correct.

The cURL command used is the one below (also tried using Insomnia):

curl --request PUT \
  --url http://localhost:8080/upload-image \
  --header 'Content-Type: multipart/form-data' \
  --form [email protected] \
  --form image=@/home/images/ad.jpg

When I print the r value as soon as it enters in the function, it shows the following result:

&{Method:PUT URL:/upload-image Proto:HTTP/1.1 ProtoMajor:1 ProtoMinor:1 Header:map[Accept:[*/*] Content-Length:[22941] Content-Type:[multipart/form-data; boundary=------------------------111a7e49ac62697b] User-Agent:[curl/7.81.0]] Body:0xc000450200 GetBody:<nil> ContentLength:22941 TransferEncoding:[] Close:false Host:localhost:8080 Form:map[] PostForm:map[] MultipartForm:<nil> Trailer:map[] RemoteAddr:127.0.0.1:59296 RequestURI:/upload-image TLS:<nil> Cancel:<nil> Response:<nil> ctx:0xc000592000 pat:<nil> matches:[] otherValues:map[]}

The code is below (I had to modify it a bit for security purposes, but in essence, that's it):

type UploadImageRequest struct {
    Email string `json:"email"`
}

func (api *Api) ValidateRequest(w http.ResponseWriter, r *http.Request) (*UploadImageRequest, error) {
    r.Body = http.MaxBytesReader(w, r.Body, maxUploadSize)

    err := r.ParseMultipartForm(maxUploadSize)
    if err != nil {
        log.Printf("ParseMultipartForm error: %v", err)
        return nil, err
    }

    email := r.FormValue("email")
    if email == "" {
        return nil, err
    }

    return &UploadImageRequest{
        Email: email,
    }, nil
}

func (api *Api) UploadImage(w http.ResponseWriter, r *http.Request) {
    fmt.Println("%+v", r)

    uploadImageRequest, err := api.ValidateRequest(w, r)
    if err != nil {
        api.app.Respond(err, w, nil)
        return
    }

    image := r.MultipartForm.File["image"]
    if len(image) == 0 {
        api.app.RespondError(nil, w, http.StatusBadRequest, "Image file is required")
        return
    }
    // ...
}

Upvotes: 2

Views: 122

Answers (2)

SirT
SirT

Reputation: 71

I suspect that at this step lead to error EOF.

http.MaxBytesReader(w, r.Body, maxUploadSize)

Please try to use:

err := r.ParseMultipartForm(32 << 20) // max memory of 32MB - adjust to how many you want

After that, if you had more process before upload to storage, maybe the result uploaded to storage become the blank image. Please add

file, err := img.Open() // This is the step you open the image and process something, maybe get size, height, width,...
file.Seek(0, 0) 

Upvotes: 0

ali alef
ali alef

Reputation: 94

Aren't you reading the request body, like using io.ReadAll(r.Body), before calling ParseMultipartForm? If the body is read, even partially, beforehand, the multipart parser will encounter an EOF error, resulting in the message: Error parsing multipart form: multipart: NextPart: EOF.

Upvotes: 0

Related Questions