client 是否支持multipart/form-data。官方好像没看到这类文档。
[gogf/gf]client 是否支持multipart/form-data
回答
@zuozhehao 客户端上传文件会自动设置multipart/form-data
,当然你也可以自定义g.Client().ContentType("multipart/form-data").Post("xxx", "xxx")
😊
https://github.com/gogf/gf/blob/master/net/ghttp/ghttp_client_request.go#L123
@gqcn
param = BuildParams(data[0])
刚才测试计算签名一直错误,这边被urlencode 了,这个是否可以外部控制。
@zuozhehao 提交参数的时候需要urlencode
,你这样传递参数试试g.Map("key1":"MTIxMg==", "file":"@file:xxx")
,你也可以在请求结束后执行response.RawDump()
看看原始请求和返回信息,参考:https://goframe.org/net/ghttp/client/demo/dump
@gqcn 测试了,urlencode导致值变化了。 用g.Map 会有排序问题,导致顺便变化,签名验证失败。
@gqcn 测试了,urlencode导致值变化了。 用g.Map 会有排序问题,导致顺便变化,签名验证失败。
go的map是无序输出的.尝试下数组看看?
你给定的提交参数是字符串就不会自动urlencode
。
签名都是需要将提交参数按照键名排序后再做处理的。
@gqcn
本地做了下测试。 图1 不带file文件概率性出错。 图2 带file 每次都出错。
@gqcn 文件能正常保存,但是参数是空的。
func TestIndex(t *testing.T) {
port := 9999
serv := g.Server(port)
serv.BindHandler("/", func(r *ghttp.Request) {
file := r.GetUploadFile("file")
_, _ = file.Save("d:/test/")
r.Response.Write("key=", r.Get("key"))
})
serv.SetPort(port)
serv.SetDumpRouterMap(false)
_ = serv.Start()
defer serv.Shutdown()
time.Sleep(1 * time.Second)
gtest.C(t, func(t *gtest.T) {
c := ghttp.NewClient()
c.SetPrefix(fmt.Sprintf("http://127.0.0.1:%d", port))
t.Assert(c.PostContent("/", "key=1&file=@file:d:/1.png"), "key=1")
})
}
@zuozhehao 你好,我使用了最新的代码没有复现你所说的问题,你可以尝试使用master
分支代码试试:https://github.com/gogf/gf/blob/develop/net/ghttp/ghttp_unit_client_test.go#L298
@zuozhehao 不带文件的单元测试我也尝试了没复现,你可以使用最新的master
分支试试:https://github.com/gogf/gf/blob/develop/net/ghttp/ghttp_unit_client_test.go#L275
@gqcn 测试了master 分支正常收到参数了,不过参数值未转义。
func TestIndex(t *testing.T) {
port := 9999
serv := g.Server(port)
serv.BindHandler("/", func(r *ghttp.Request) {
r.Response.Write("key=", r.Get("key"))
})
serv.SetPort(port)
serv.SetDumpRouterMap(false)
_ = serv.Start()
defer serv.Shutdown()
time.Sleep(1 * time.Second)
gtest.C(t, func(t *gtest.T) {
c := ghttp.NewClient()
c.SetPrefix(fmt.Sprintf("http://127.0.0.1:%d", port))
t.Assert(c.PostContent("/", "key=a+b"), "key=a+b")
})
}