diff --git a/net/ghttp/ghttp_client_request.go b/net/ghttp/ghttp_client_request.go index 0c1a6251a..f68a1935d 100644 --- a/net/ghttp/ghttp_client_request.go +++ b/net/ghttp/ghttp_client_request.go @@ -123,7 +123,7 @@ func (c *Client) DoRequest(method, url string, data ...interface{}) (resp *Clien param = BuildParams(data[0]) } } - req := (*http.Request)(nil) + var req *http.Request if strings.Contains(param, "@file:") { // File uploading request. buffer := new(bytes.Buffer) diff --git a/net/ghttp/ghttp_func.go b/net/ghttp/ghttp_func.go index 26d32e45e..5c69f3bec 100644 --- a/net/ghttp/ghttp_func.go +++ b/net/ghttp/ghttp_func.go @@ -8,12 +8,17 @@ package ghttp import ( "github.com/gogf/gf/errors/gerror" + "github.com/gogf/gf/text/gstr" "strings" "github.com/gogf/gf/encoding/gurl" "github.com/gogf/gf/util/gconv" ) +const ( + fileUploadingKey = "@file:" +) + // BuildParams builds the request string for the http client. The can be type of: // string/[]byte/map/struct/*struct. // @@ -38,13 +43,22 @@ func BuildParams(params interface{}, noUrlEncode ...bool) (encodedParamStr strin if len(noUrlEncode) == 1 { urlEncode = !noUrlEncode[0] } + // If there's file uploading, it ignores the url encoding. + if urlEncode { + for k, v := range m { + if gstr.Contains(k, fileUploadingKey) || gstr.Contains(gconv.String(v), fileUploadingKey) { + urlEncode = false + break + } + } + } s := "" for k, v := range m { if len(encodedParamStr) > 0 { encodedParamStr += "&" } s = gconv.String(v) - if urlEncode && len(s) > 6 && strings.Compare(s[0:6], "@file:") != 0 { + if urlEncode && len(s) > 6 && strings.Compare(s[0:6], fileUploadingKey) != 0 { s = gurl.Encode(s) } encodedParamStr += k + "=" + s diff --git a/net/ghttp/ghttp_unit_client_test.go b/net/ghttp/ghttp_unit_client_test.go index 3a87236e3..ef159e5e5 100644 --- a/net/ghttp/ghttp_unit_client_test.go +++ b/net/ghttp/ghttp_unit_client_test.go @@ -295,6 +295,8 @@ func Test_Client_Param_Containing_Special_Char(t *testing.T) { }) } +// It posts data along with file uploading. +// It does not url-encodes the parameters. func Test_Client_File_And_Param(t *testing.T) { p, _ := ports.PopRand() s := g.Server(p) @@ -308,7 +310,7 @@ func Test_Client_File_And_Param(t *testing.T) { _, err = file.Save(tmpPath) gtest.Assert(err, nil) r.Response.Write( - r.Get("key"), + r.Get("json"), gfile.GetContents(gfile.Join(tmpPath, gfile.Basename(file.Filename))), ) }) @@ -320,12 +322,13 @@ func Test_Client_File_And_Param(t *testing.T) { time.Sleep(100 * time.Millisecond) gtest.C(t, func(t *gtest.T) { + path := gdebug.TestDataPath("upload", "file1.txt") + data := g.Map{ + "file": "@file:" + path, + "json": `{"uuid": "luijquiopm", "isRelative": false, "fileName": "test111.xls"}`, + } c := g.Client() c.SetPrefix(fmt.Sprintf("http://127.0.0.1:%d", p)) - filePath := gdebug.TestDataPath("upload", "file1.txt") - t.Assert( - c.PostContent("/", "key=1&file=@file:"+filePath), - "1"+gfile.GetContents(filePath), - ) + t.Assert(c.PostContent("/", data), data["json"].(string)+gfile.GetContents(path)) }) }