Golang post 模拟表单上传文件第三方服务器

函数封装

// @see https://studygolang.com/articles/21194?fr=sidebar
// @see https://github.com/GeraltXLi/go-tools/tree/master/http
// 该参考地址另有封装的GET, POST请求等方法

// HttpClient 注意client 本身是连接池,不要每次请求时创建client
var (
    HttpClient *http.Client
)

func InitHttpClient()  {
    HttpClient = &http.Client{
        Timeout: 30 * time.Second, // 请求超时时间
    }
}

// UploadFile 发送文件上传请求
func UploadFile(url string, params map[string]string, nameField, filename string, file io.Reader) ([]byte, error) {
    body := new(bytes.Buffer)

    writer := multipart.NewWriter(body)

    // 在表单中创建一个文件字段
    formFile, err := writer.CreateFormFile(nameField, filename)
    if err != nil {
        return nil, err
    }

    // 读取文件内容到表单文件字段
    _, err = io.Copy(formFile, file)
    if err != nil {
        return nil, err
    }

    // 将其他参数写入到表单
    for key, val := range params {
        _ = writer.WriteField(key, val)
    }

    if err = writer.Close(); err != nil {
        return nil, err
    }

    // 构造请求对象
    req, err := http.NewRequest("POST", url, body)
    if err != nil {
        return nil, err
    }
    //req.Header.Set("Content-Type","multipart/form-data")
    req.Header.Add("Content-Type", writer.FormDataContentType())

    // 发送请求
    resp, err := HttpClient.Do(req)
    if err != nil {
        return nil, err
    }
    defer resp.Body.Close()

    return ioutil.ReadAll(resp.Body)
}

调用方法

utils.InitHttpClient()

// 要上传的文件地址
filePath := `D:\wwwroot\example.txt`

// 打开文件句柄
srcFile, err := os.Open(filePath)
if err != nil {
    fmt.Println("os.Open.err", err)
}

// 文件上传时的额外参数
params := map[string]string{
    "param": `example`,
}

_, err = utils.UploadFile(`http://127.0.0.1:8080/uploadFile`, params, "file", "example.txt", srcFile)
if err != nil {
    fmt.Println("UploadFile.err", err)
} else {
    fmt.Println("UploadFile.success", string(resp))
}

调用方法(批量上传)

var fileList []FileInfo
GetFileList(path, &fileList)

fmt.Println("文件数量:", len(fileList))

fmt.Println("begin:", time.Now())

// 批量上传只需要初始化一次请求池
utils.InitHttpClient()

// 遍历文件上传
for _, file := range fileList {
    fmt.Println("file", file.Name, file.Size, file.Path)

    // 打开文件句柄
    srcFile, err := os.Open(file.Path)
    if err != nil {
        fmt.Println("os.Open.err", file.Name, err)
    }

    // todo: 增加文件大小和md5/sha1校验值
    // 文件上传时的额外参数
    params := map[string]string{
        //name: file.Name,
        //size: strconv.FormatInt(file.Size, 10),
        "path": strings.Replace(file.Path[len(path):], `\`, `/`, -1),
    }

    _, err = utils.UploadFile(global.Config.ServerUrl, params, "file", file.Name, srcFile)
    if err != nil {
        fmt.Println("UploadFile.err", file.Name, err)
    } else {
        //fmt.Println("UploadFile.success", file.Name, string(resp))
    }
}
fmt.Println("end:", time.Now())