多部分编写器 CreateFormFile 卡住了

multipart writer CreateFormFile stuck

尝试使用 gopostmultipart/form-data 图像

图像文件从请求客户端接收并已保存为 multipart.File

这是我的代码

func postImage(file multipart.File, url string, filename string) (*http.Response, error) {
    r, w := io.Pipe()
    defer w.Close()
    m := multipart.NewWriter(w)
    defer m.Close()

    errchan := make(chan error)
    defer close(errchan)

    go func() {
        part, err := m.CreateFormFile("file", filename)
        log.Println(err)
        if err != nil {
            errchan <- err
            return
        }

        if _, err := io.Copy(part, file); err != nil {
            errchan <- err
            return
        }
    }()

    merr := <-errchan
    if merr != nil {
        return nil, merr
    }

    resp, err := http.Post(url, m.FormDataContentType(), r)
    if err != nil {
        return nil, err
    }
    defer resp.Body.Close()

    return resp, err
}

当我尝试使用它时,它停留在 part, err := m.CreateFormFile("file", filename) 从来没有 return 任何东西

有什么解决办法吗?

谢谢

使用管道错误将错误传播回主 goroutine。关闭管道的写入端以防止客户端在读取时永远阻塞。关闭管道的读取端以确保 goroutine 退出。

func postImage(file multipart.File, url string, filename string) (*http.Response, error) {
    r, w := io.Pipe()

    // Close the read side of the pipe to ensure that
    // the goroutine exits in the case where http.Post
    // does not read all of the request body.
    defer r.Close()

    m := multipart.NewWriter(w)

    go func() {
        part, err := m.CreateFormFile("file", filename)
        if err != nil {
            // The error is returned from read on the pipe.
            w.CloseWithError(err)
            return
        }
        if _, err := io.Copy(part, file); err != nil {
            // The error is returned from read on the pipe.
            w.CloseWithError(err)
            return
        }
        // The http.Post function reads the pipe until 
        // an error or EOF. Close to return an EOF to
        // http.Post.
        w.Close()
    }()

    resp, err := http.Post(url, m.FormDataContentType(), r)
    if err != nil {
        return nil, err
    }
    defer resp.Body.Close()

    return resp, err
}