Golang Form Request

使用 go 创建 form 表单请求,创建文件上传请求

示例代码实现 typora 自定义图片上传服务规则,上传图片到自定义服务

参考文章: 点我跳转 ,一篇很详细的 form 教程文章

创建表单并设置值和文件信息

func createRequestBody(filePathArray []string) (string, io.Reader, error) {
	buf := new(bytes.Buffer)
	bw := multipart.NewWriter(buf) // 创建表单,获取一个 writer

	// 处理文件路径列表为文件名字符串
	var fileListString string
	for i, l := 0, len(filePathArray); i < l; i++ {

		filePath := filePathArray[i]
    // 当本地文件路径包含中文时,typora 会对中文编码,这里解码还原在继续处理
    filePath, err := url.QueryUnescape(filePath)
		if err != nil {
			return "", nil, err
		}
		fileName := filepath.Base(filePath)
		suffixName := path.Ext(filePath)
		if !supportSuffix(suffixName) {
			return "", nil, fmt.Errorf("file %s not support", filePath)
		}

		if i == l-1 {
			fileListString += fileName
		} else {
			fileListString += fileName + ","
		}
	}

	// 用户信息
	err := bw.WriteField("username", username)
	if err != nil {
		return "", nil, err
	}

	h := md5.New()
	h.Write([]byte(passwd))
	err = bw.WriteField("passwd", hex.EncodeToString(h.Sum(nil)))
	if err != nil {
		return "", nil, err
	}
	// 上传文件列表
	err = bw.WriteField("file_list", fileListString)
	if err != nil {
		return "", nil, err
	}

	// 读取文件添加到 form 表单中
	for i, l := 0, len(filePathArray); i < l; i++ {
		filePath := filePathArray[i]
    filePath, err := url.QueryUnescape(filePath)
		if err != nil {
			return "", nil, err
		}
		fileName := filepath.Base(filePath)
		file, err := os.Open(filePath)
		if err != nil {
			return "", nil, err
		}
    // 可以看一下 CreateFormFile 源码,直接复制过来修改,用来实现分别描述不同文件的,文件类型
    // 默认的 Content-Type 都是 application/octet-stream
		formFileWriter, err := bw.CreateFormFile(fileName, fileName)
		if err != nil {
			return "", nil, err
		}
		io.Copy(formFileWriter, file)
		err = file.Close()
		if err != nil {
			return "", nil, err
		}
	}
	_ = bw.Close()  // 必须关闭写入
	return bw.FormDataContentType(), buf, nil
}

创建好之后就可以发送到接口了,下面给出一个简单的示例

func doUploadRequest(url, contentType string, body io.Reader) (string, error) {
	httpClient := &http.Client{}  // 创建 http 请求客户端
	request, err := http.NewRequest("POST", url, body)  // 创建 POST 请求
	if err != nil {
		return "", err
	}
	request.Header.Set("Content-Type", contentType)  // 设置 content-type 为表单类型

	resp, err := httpClient.Do(request)  // 发送请求
	if err != nil {
		return "", err
	}
	defer func() {
		_ = resp.Body.Close()
	}()

	result, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return "", err
	}
	return string(result), nil
}

typora自定义上传命令设置

typora自定义上传测试