Search code examples
javascripthtmlajaxgomultipart

Ajax Upload File to GoLang Server with Content Type Multipart


I'm trying to upload an audio file to a Golang server using a multipart form. However, Go returns the error:

multipart: NextPart: bufio: buffer full

I believe this indicates there is something not in the multipart format with my Javascript request. This is my Javascript:

function UploadFile(file) {
    var xhr = new XMLHttpRequest();


    if (file.type == "audio/mpeg" && file.size <= $id("MAX_FILE_SIZE").value) {
        // start upload
        var boundary = '---------------------------' + Math.floor(Math.random()*32768) + Math.floor(Math.random()*32768) + Math.floor(Math.random()*32768);

        xhr.open("POST", $id("upload").action, true);
        xhr.setRequestHeader("Content-Type", "multipart/form-data; boundary=" + boundary);
        xhr.setRequestHeader("X_FILENAME", file.name);
        xhr.send(file);
    }
}

And this is my Golang server handler:

func FileHandler(w http.ResponseWriter, r *http.Request) {
    var (
        status int
        err    error
    )
    defer func() {
        if nil != err {
            http.Error(w, err.Error(), status)
        }
    }()
    // parse request with maximum memory of _24Kilobits
    const _24K = (1 << 20) * 24
    if err = r.ParseMultipartForm(_24K); nil != err {
        fmt.Println(err)
        status = http.StatusInternalServerError
        return
    }
    for _, fheaders := range r.MultipartForm.File {
        for _, hdr := range fheaders {
            // open uploaded
            var infile multipart.File
            if infile, err = hdr.Open(); nil != err {
                status = http.StatusInternalServerError
                return
            }
            // open destination
            var outfile *os.File
            if outfile, err = os.Create("./uploaded/" + hdr.Filename); nil != err {
                status = http.StatusInternalServerError
                return
            }
            // 32K buffer copy
            var written int64
            if written, err = io.Copy(outfile, infile); nil != err {
                status = http.StatusInternalServerError
                return
            }
        w.Write([]byte("uploaded file:" + hdr.Filename + ";length:" + strconv.Itoa(int(written))))
        }
    }
}

If anyone has any ideas why I'm getting this error, I'd greatly appreciate it.


Solution

  • After a long, arduous battle with the Ajax request, I got it to send the right information. Here's the code I used:

    var xhr = new XMLHttpRequest(),
        boundary=Math.random().toString().substr(2);
    
    var formdata = new FormData();
    formdata.append("file", file);
    
    xhr.open("POST", $id("upload").action, true);
    //xhr.setRequestHeader("content-type", "multipart/form-data; charset=utf-8; boundary=" + boundary);
    xhr.send(formdata);
    

    Note the header is no longer in use and I found you can attach data to formdata much easier than any other method such as this: How to send multipart/form-data form content by ajax (no jquery)?