Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Multipart file upload name parameter is not configurable #617

Closed
TLINDEN opened this issue Feb 20, 2023 · 5 comments
Closed

Multipart file upload name parameter is not configurable #617

TLINDEN opened this issue Feb 20, 2023 · 5 comments
Assignees

Comments

@TLINDEN
Copy link

TLINDEN commented Feb 20, 2023

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!

@jeevatkm
Copy link
Member

jeevatkm commented Mar 6, 2023

@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)?

@TLINDEN
Copy link
Author

TLINDEN commented Mar 6, 2023

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

@jeevatkm
Copy link
Member

jeevatkm commented Mar 8, 2023

@TLINDEN Thanks for sharing the code snippet. I will have a look and try to understand the context of the issue.

@gospider007
Copy link

如果您上传了多个文件,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

@jeevatkm jeevatkm self-assigned this Oct 4, 2024
@jeevatkm
Copy link
Member

jeevatkm commented Oct 4, 2024

This has been handled in Resty v3 development, PR #879. It is currently available in the main branch. The following methods allow the same field name for multiple files.

  • Request.SetFile
  • Request.SetFileReader
  • Request.SetMultipartField
  • Request.SetMultipartFields

The method Request.SetFiles will not help since the parameter type is map[string]string; the map will not support duplicate keys.

@jeevatkm jeevatkm closed this as completed Oct 4, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

No branches or pull requests

3 participants