POST data using the Content-Type multipart/form-data

后端 未结 7 1441
小鲜肉
小鲜肉 2020-11-27 12:16

I\'m trying to upload images from my computer to a website using go. Usually, I use a bash script that sends a file and a key to the server:

curl -F \"image         


        
7条回答
  •  醉梦人生
    2020-11-27 13:20

    Here's a function I've used that uses io.Pipe() to avoid reading in the entire file to memory or needing to manage any buffers. It handles only a single file, but could easily be extended to handle more by adding more parts within the goroutine. The happy path works well. The error paths have not hand much testing.

    import (
        "fmt"
        "io"
        "mime/multipart"
        "net/http"
        "os"
    )
    
    func UploadMultipartFile(client *http.Client, uri, key, path string) (*http.Response, error) {
        body, writer := io.Pipe()
    
        req, err := http.NewRequest(http.MethodPost, uri, body)
        if err != nil {
            return nil, err
        }
    
        mwriter := multipart.NewWriter(writer)
        req.Header.Add("Content-Type", mwriter.FormDataContentType())
    
        errchan := make(chan error)
    
        go func() {
            defer close(errchan)
            defer writer.Close()
            defer mwriter.Close()
    
            w, err := mwriter.CreateFormFile(key, path)
            if err != nil {
                errchan <- err
                return
            }
    
            in, err := os.Open(path)
            if err != nil {
                errchan <- err
                return
            }
            defer in.Close()
    
            if written, err := io.Copy(w, in); err != nil {
                errchan <- fmt.Errorf("error copying %s (%d bytes written): %v", path, written, err)
                return
            }
    
            if err := mwriter.Close(); err != nil {
                errchan <- err
                return
            }
        }()
    
        resp, err := client.Do(req)
        merr := <-errchan
    
        if err != nil || merr != nil {
            return resp, fmt.Errorf("http error: %v, multipart error: %v", err, merr)
        }
    
        return resp, nil
    }
    

提交回复
热议问题