Go如何模拟前端发送MultiForm类型信息
起因#
最开始我是使用APIPost模拟前端发送消息的,但是到了需要发送多个文件的需求的时候就有点问题了。因为它不能多选文件...官方给出的解决办法是这样的:
https://qa.apipost.cn/q/89d67962d3022577
目前是按照以下方式传输的
update: 结果发现APIPost7已经支持了,我是小丑
所以最后用PostMan选择多个上传了。但是!!因为这个URL每次都要权限验证,所以每次都要登录之后获取Token再去跑URL,非常麻烦!于是就考虑自己写HTTP Client去模拟用户行为。然后就去网上找,Go的Http包怎么样才能模拟发送MultiForm请求。
过程#
网上大多都是这样子
Go-post上传多文件和其它参数:两个key名(我的需求是一个key名下面有两个文件,并且还要发送键值对
func (c *PostGetController) sendPostFormFile(url string, filename string)(error) {
body_buf := bytes.NewBufferString("")
body_writer := multipart.NewWriter(body_buf)
// boundary默认会提供一组随机数,也可以自己设置。
body_writer.SetBoundary("Pp7Ye2EeWaFDdAY");
//boundary := body_writer.Boundary()
// 1. 要上传的数据
body_writer.WriteField("key1", "value-string1")
body_writer.WriteField("key2", fmt.Sprintf("%d", 45))
// 2. 内存中的文件1,FormFile1
_, err := body_writer.CreateFormFile("filekey1", "filename.txt")
if err != nil {
fmt.Printf("创建FormFile1文件信息异常!", err)
return err
}
f1_content := "内存中文件1的内容";
body_buf.Write([]byte(f1_content))
// 3. 读取文件
_, errr := body_writer.CreateFormFile("filekey2", filename)
if errr != nil {
fmt.Printf("创建FormFile2文件信息异常!", err)
return errr
}
fb2, err := ioutil.ReadFile(filename)
if err != nil {
fmt.Println("打开文件异常!", err)
return err
}
body_buf.Write(fb2)
// 结束整个消息body
body_writer.Close();
//
req_reader := io.MultiReader(body_buf)
req, err := http.NewRequest("POST", url, req_reader)
if err != nil {
fmt.Printf("站点相机上传图片,创建上次请求异常!异常信息:", err)
return err
}
// 添加Post头
req.Header.Set("Connection", "close")
req.Header.Set("Pragma", "no-cache")
req.Header.Set("Content-Type", body_writer.FormDataContentType())
req.ContentLength = int64(body_buf.Len())
fmt.Printf("发送消息长度:", req.ContentLength)
// 发送消息
client := &http.Client{}
resp, err := client.Do(req)
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
fmt.Printf("读取回应消息异常:", err)
}
fmt.Printf("发送回应数据:",string(body))
return nil
}
要么就是只有一个文件...这里就不放代码了,上面类似
解决方案#
最后终于在一个不知名的第三方网站发现了 Http Post 发送文件流案例
其实说白了,就是Create两个名字相同的FormFile,写入就好了,具体可以看到代码关键部分
// key:file 里面放多个文件
// multipart/form-data 传多个文件
func postFormDataWithMultipartFile() {
client := http.Client{}
bodyBuf := &bytes.Buffer{}
bodyWrite := multipart.NewWriter(bodyBuf)
images := []string{"img.jpg", "img1.jpg"}
for _, val := range images {
file, err := os.Open("./images/" + val)
defer file.Close()
if err != nil {
log.Println("err")
}
// !!!关键代码是这里
fileWrite, err := bodyWrite.CreateFormFile("file", val)
_, err = io.Copy(fileWrite, file)
if err != nil {
log.Println("err")
}
}
bodyWrite.Close() //要关闭,会将w.w.boundary刷写到w.writer中
// 创建请求
req, err := http.NewRequest(http.MethodPost, imagePostURL, bodyBuf)
if err != nil {
log.Println("err")
}
// 设置头
contentType := bodyWrite.FormDataContentType()
req.Header.Set("Content-Type", contentType)
resp, err := client.Do(req)
if err != nil {
log.Println("err")
}
defer resp.Body.Close()
b, err := ioutil.ReadAll(resp.Body)
if err != nil {
log.Println("err")
}
fmt.Println(string(b))
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· winform 绘制太阳,地球,月球 运作规律
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人