resty
resty copied to clipboard
Multipart file upload name parameter is not configurable
If you upload multiple files resty sets the name= form-data parameter to the filename of each file, e.g. when uploading 2 files, xxx and yyy:
~~~ REQUEST ~~~
POST /api/putfile HTTP/1.1
HOST : localhost:8080
HEADERS:
Content-Type: multipart/form-data; boundary=816c85ff0952ec600652e0d86e3f22b74386606efe95028accd9b995e1f4
User-Agent: go-resty/2.7.0 (https://github.com/go-resty/resty)
BODY :
--816c85ff0952ec600652e0d86e3f22b74386606efe95028accd9b995e1f4
Content-Disposition: form-data; name="yyy"; filename="yyy"
Content-Type: application/octet-stream
Mon Feb 20 07:48:40 PM CET 2023
--816c85ff0952ec600652e0d86e3f22b74386606efe95028accd9b995e1f4
Content-Disposition: form-data; name="xxx"; filename="xxx"
Content-Type: application/octet-stream
Fri Feb 17 01:00:11 PM CET 2023
--816c85ff0952ec600652e0d86e3f22b74386606efe95028accd9b995e1f4
Content-Disposition: form-data; name="expire"
1d
--816c85ff0952ec600652e0d86e3f22b74386606efe95028accd9b995e1f4--
The problem is, I am using GIN on the receiving end and want to fetch all the uploaded files, which is currently not possible because there's no array with a shared name parameter.
Here's how such a request should look if done right, using:
curl -X POST localhost:8080/api/putfile -F "upload[]=@xxx" -F "upload[]=@yyy" -H "Content-Type: multipart/form-data"
posted content:
POST /api/putfile HTTP/1.1
Host: localhost:8080
User-Agent: curl/7.81.0
Accept: */*
Content-Length: 416
Content-Type: multipart/form-data; boundary=------------------------93a472d0d0bc7413
--------------------------93a472d0d0bc7413
Content-Disposition: form-data; name="upload[]"; filename="xxx"
Content-Type: application/octet-stream
Fri Feb 17 01:00:11 PM CET 2023
--------------------------93a472d0d0bc7413
Content-Disposition: form-data; name="upload[]"; filename="yyy"
Content-Type: application/octet-stream
Mon Feb 20 07:48:40 PM CET 2023
--------------------------93a472d0d0bc7413--
It is possible to circumnavigate this issue by manually populating the form data using SetMultipartFields. But this is a tedious job, which resty already does very well- in fact that's one of the very reasons I'm trying to use it.
So, a method to set this name to a unique array over all uploaded files is required, something like SetFormDataName which then must set this parameter and append []. At least this would help me a lot!
@TLINDEN Thanks for reaching out. I think I'm able to follow, still didn't get a full understanding. Could you please provide test case to demonstrate your use case/issue (client side and server side)?
Yeah, this is (better: was, 'cause in the meantime I switched to another module) the client code:
package lib
import (
"encoding/json"
"fmt"
"github.com/go-resty/resty/v2"
"os"
"path/filepath"
)
type Response struct {
Code int `json:"code"`
Success bool `json:"success"`
Message string `json:"message"`
}
func Runclient(cfg *cfg.Config, args []string) error {
client := resty.New()
client.SetDebug(cfg.Debug)
url := cfg.Endpoint + "/putfile"
files := os.Args[1:]
postfiles := make(map[string]string)
for _, file := range files {
postfiles[filepath.Base(file)] = file
}
resp, err := client.R().
SetFiles(postfiles).
SetFormData(map[string]string{"expire": "1d"}).
Post(url)
if cfg.Debug {
fmt.Println("Response Info:")
fmt.Println(" Error :", err)
fmt.Println(" Status Code:", resp.StatusCode())
fmt.Println(" Status :", resp.Status())
fmt.Println(" Proto :", resp.Proto())
fmt.Println(" Time :", resp.Time())
fmt.Println(" Received At:", resp.ReceivedAt())
fmt.Println(" Body :\n", resp)
fmt.Println()
}
r := Response{}
json.Unmarshal([]byte(resp.String()), &r)
fmt.Println(r)
}
Serverside code is here
@TLINDEN Thanks for sharing the code snippet. I will have a look and try to understand the context of the issue.
如果您上传了多个文件,resty 将 form-data 参数设置为每个文件的文件名,例如在上传 2 个文件时,并且:
name=``xxx``yyy~~~ REQUEST ~~~ POST /api/putfile HTTP/1.1 HOST : localhost:8080 HEADERS: Content-Type: multipart/form-data; boundary=816c85ff0952ec600652e0d86e3f22b74386606efe95028accd9b995e1f4 User-Agent: go-resty/2.7.0 (https://github.com/go-resty/resty) BODY : --816c85ff0952ec600652e0d86e3f22b74386606efe95028accd9b995e1f4 Content-Disposition: form-data; name="yyy"; filename="yyy" Content-Type: application/octet-stream Mon Feb 20 07:48:40 PM CET 2023 --816c85ff0952ec600652e0d86e3f22b74386606efe95028accd9b995e1f4 Content-Disposition: form-data; name="xxx"; filename="xxx" Content-Type: application/octet-stream Fri Feb 17 01:00:11 PM CET 2023 --816c85ff0952ec600652e0d86e3f22b74386606efe95028accd9b995e1f4 Content-Disposition: form-data; name="expire" 1d --816c85ff0952ec600652e0d86e3f22b74386606efe95028accd9b995e1f4--问题是,我在接收端使用 GIN 并想获取所有上传的文件,这目前是不可能的,因为没有带有共享名称参数的数组。
如果操作得当,此类请求应如下所示,使用:
curl -X POST localhost:8080/api/putfile -F "upload[]=@xxx" -F "upload[]=@yyy" -H "Content-Type: multipart/form-data"发布内容:
POST /api/putfile HTTP/1.1 Host: localhost:8080 User-Agent: curl/7.81.0 Accept: */* Content-Length: 416 Content-Type: multipart/form-data; boundary=------------------------93a472d0d0bc7413 --------------------------93a472d0d0bc7413 Content-Disposition: form-data; name="upload[]"; filename="xxx" Content-Type: application/octet-stream Fri Feb 17 01:00:11 PM CET 2023 --------------------------93a472d0d0bc7413 Content-Disposition: form-data; name="upload[]"; filename="yyy" Content-Type: application/octet-stream Mon Feb 20 07:48:40 PM CET 2023 --------------------------93a472d0d0bc7413--可以通过使用 手动填充表单数据来规避此问题。但这是一项乏味的工作,resty 已经做得很好了——事实上,这也是我尝试使用它的原因之一。
SetMultipartFields因此,需要一种方法来将此名称设置为所有上传文件的唯一数组,例如必须设置此参数并附加 .至少这会对我有很大帮助!
SetFormDataName``[]
this can help you : https://github.com/gospider007/requests/blob/master/test/request/file_test.go