Golang Form Request

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

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

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
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
}

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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自定义上传测试