首页 > 解决方案 > 使用 io.pipe 遇到 multipart.NewWriter 问题

问题描述

我遇到了随机发送空请求的问题。它并不总是发生,但有时出乎意料,它不会发送任何多部分字段。我认为这可能与上传服务器有关,所以我创建了一个本地上传服务器来打印正在发送的请求,结果它是空的。

我在所有地方都添加了错误检查,但没有返回任何错误。

我尝试使用 -race 运行代码,但没有报告任何竞争条件。

编辑:更新要使用的代码CloseWithError()

 package main

import (
    "fmt"
    "io"
    "log"
    "mime/multipart"
    "net/http"
    "os"
)

var (
    upload_url     string = "https://upload.imagekit.io/api/v1/files/upload"
    file_name      string = "favicon-516140983.ico"
    api_secret_key string = "PRIVATE_KEY"
)

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 {
        log.Println(err)
        return nil, err
    }

    mwriter := multipart.NewWriter(writer)
    req.Header.Add("Content-Type", mwriter.FormDataContentType())
    req.SetBasicAuth(api_secret_key, "")

    go func() {

        var err error

        defer func() {

            if err != nil {

                writer.CloseWithError(err)
            } else {

                writer.Close()
            }

        }()

        var file *os.File
        file, err = os.Open(path)
        if err != nil {

            return
        }

        defer file.Close()

        if err = mwriter.WriteField("fileName", file_name); err != nil {

            return
        }

        var w io.Writer

        w, err = mwriter.CreateFormFile("file", path)
        if err != nil {

            return
        }
        var written int64
        if written, err = io.Copy(w, file); err != nil {

            err = fmt.Errorf("error copying %s (%d bytes written): %v", path, written, err)

            return
        }

        if err = mwriter.Close(); err != nil {

            return
        }
    }()

    resp, err := client.Do(req)

    if err != nil {
        return nil, err
    }

    return resp, nil
}

func main() {
    path, _ := os.Getwd()

    path += "/" + file_name

    client := &http.Client{}

    resp, err := UploadMultipartFile(client, upload_url, "file", path)

    if err != nil {

        log.Println(err)
    } else {

        fmt.Println(resp.StatusCode)
        fmt.Println(resp.Header)

        _, err := io.Copy(os.Stdout, resp.Body)
        if err != nil {
        log.Fatal(err)
        }
        resp.Body.Close()
    }
}

标签: go

解决方案


推荐阅读