RicoSuter / NSwag

The Swagger/OpenAPI toolchain for .NET, ASP.NET Core and TypeScript.
http://NSwag.org
MIT License
6.73k stars 1.29k forks source link

Multiple file upload via UI #1421

Open Fedorus opened 6 years ago

Fedorus commented 6 years ago

Is there a way to send multiple files in one request using:

app.UseSwaggerUi(typeof(Startup).GetTypeInfo().Assembly, settings =>{
               settings.UseJsonEditor = true;
            });

first of all it allows selection of only 1 file. And after that in file: NSwag.AspNet.Owin/SwaggerUi/swagger-ui.js it just doesn`t add files:

      if (o.type === 'file') {
        map[o.name] = o.files[0];
      }
RicoSuter commented 6 years ago

Seems to be a problem with swagger ui and not nswag. Did you try SwaggerUi3? Is the generated swagger spec correct? Where did you find the last code snippet?

Fedorus commented 6 years ago

Where did you find the last code snippet?

link

Is the generated swagger spec correct?

Yes, spec is correct.

Did you try SwaggerUi3?

Hm, I`ll look on it today, thanks.

Fedorus commented 6 years ago

Same thing with 3rd version. HTTP side doesn`t use "multiple" atribute and if you add it will still send only first file. The generated side looks good:

{ "type": "file", "name": "files", "in": "formData", "collectionFormat": "multi", "x-nullable": true, "items": { "type": "file" }

RicoSuter commented 6 years ago

Maybe you should check with the Swagger UI 3 guys whether this is supported and correct Swagger spec?

https://github.com/swagger-api/swagger-ui

BramMusters commented 6 years ago

Yes there is, the following shows a file upload for me, in both Swagger UI 2 and 3 :

public async Task<List<X>> X([FromForm] IFormFile file1, [FromForm] IFormFile file2)
{
            file1 = this.HttpContext.Request.Form.Files[0];
            file2 = this.HttpContext.Request.Form.Files[1];

For some reason the files are not bound correctly by ASP.NET Core, so that's why I get it manually from the request's context.

Which brings me to the following problem: The above approach only works for app.UserSwaggerUi(3), if I'm using the new ApiExplorer approach, the file upload is not recognized, as can be seen in the following screencap: capture

ranouf commented 6 years ago

Hi,

I try to transfer an array of IFile from Angular to .Net Core. It seems that I have the same issue. my variable [FromForm] has all properties to null.

Did you find a way to bind it automatically?

here is my Dto

Server:

    public class SampleDto
    {
        public Guid Id{ get; set; }
        public string Text { get; set; }
        public IEnumerable<string> ImageUrl { get; set; }
        public IEnumerable<IFormFile> Image { get; set; }
    }

        [HttpPut]
        [Route("{id:guid}")]
        public async Task<IActionResult> UpdateAsync([FromRoute]Guid id, [FromForm] SampleDto dto)
        {
           Console.WriteLine(dto.Text); //Return null
           Console.WriteLine(dto.Image[0]?.FileName); //Return null

            return Ok();
        }

Here is the value of my Form image

Here is what the browser send: image

Here is the code generated by nswag:

 update(id: string, dto: SampleDto | null | undefined): Observable<SampleDto | null> {
        let url_ = this.baseUrl + "/api/v1/Sample/{id}";
        if (id === undefined || id === null)
            throw new Error("The parameter 'id' must be defined.");
        url_ = url_.replace("{id}", encodeURIComponent("" + id)); 
        url_ = url_.replace(/[?&]$/, "");

        const content_ = new FormData();
        if (dto !== null && dto !== undefined)
            content_.append("dto", dto.toString());

        let options_ : any = {
            body: content_,
            observe: "response",
            responseType: "blob",
            headers: new HttpHeaders({
                "Accept": "application/json"
            })
        };

        return _observableFrom(this.transformOptions(options_)).pipe(_observableMergeMap(transformedOptions_ => {
            return this.http.request("put", url_, transformedOptions_);
        })).pipe(_observableMergeMap((response_: any) => {
            return this.transformResult(url_, response_, (r) => this.processUpdate(<any>r));
        })).pipe(_observableCatch((response_: any) => {
            if (response_ instanceof HttpResponseBase) {
                try {
                    return this.transformResult(url_, response_, (r) => this.processUpdate(<any>r));
                } catch (e) {
                    return <Observable<SampleDto | null>><any>_observableThrow(e);
                }
            } else
                return <Observable<SampleDto | null>><any>_observableThrow(response_);
        }));
    }

Here there is a repo where it s possible to upload data and File: https://github.com/fiyazbinhasan/AngularSpaCore

In Swagger, the array of IFormFile seems to be manage correctly now:

image

zuckerthoben commented 5 years ago

I have the same problem as @barmyard. With ApiExplorer my Upload Actions are not detected correctly. Any updates?

MennoVisser91 commented 5 years ago

I have the same problem. Any updates???

JonasDev17 commented 4 years ago

This is actually a swagger-ui issue. Go vote for it by giving a thumbs up: https://github.com/swagger-api/swagger-ui/issues/4600

RicoSuter commented 4 years ago

So the generated spec is correct and we have to wait for a swagger ui update?

Fedorus commented 4 years ago

I`m shoked that this bug is still exist,,,

JonasDev17 commented 4 years ago

So the generated spec is correct and we have to wait for a swagger ui update?

I think so, yes...

Juice-XIJ commented 4 years ago

Hi @RicoSuter at this moment the swagger issue just fixed a few days ago.

I updated NSwag to 13.6.0. Now the generated swagger.json looks like:

"requestBody": {
    "content": {
        "multipart/form-data": {
            "schema": {
                "type": "object",
                "properties": {
                    "audioFileList": {
                        "type": "array",
                        "items": {
                            "type": "string",
                            "format": "binary"
                        }
                    }
                }
            }
        }
    }
}

This schema is the same as latest swagger client. However when I use the swagger ui to send request to the sever, I found that the request is like:

Host: localhost:8446
Connection: keep-alive
Content-Length: 157
accept: application/json
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36 Edg/83.0.478.37
Ocp-Apim-Subscription-Key: 5b9e48e85daf4c32aab4d403d0eea5cd
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryplFirfy6HmAbgpAl
Origin: https://localhost:8446
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: cors
Sec-Fetch-Dest: empty
Referer: https://localhost:8446/UI/index.html?urls.primaryName=OpenApi%203.0
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Cookie: ai_user=I8/5h|2020-04-18T00:44:53.179Z; grafana_session=348d3dc50bd60b4c0045046d35440dc9

------WebKitFormBoundaryplFirfy6HmAbgpAl
Content-Disposition: form-data; name="audioFileList"

[object File]
------WebKitFormBoundaryplFirfy6HmAbgpAl--

The request only sent string '[object file]" instead of the form data that I selected (also, content length is only 157).

Hence, any thoughts about it? Thanks!

dmitry-pavlov commented 4 years ago

I confirm that:

What I use:

So it's fine except using Swagger UI 3 for uploading files. Any workarounds how to make Swagger UI sending correct data?

RicoSuter commented 4 years ago

Do we need to update Swagger UI 3 in NSwag.AspNetCore? Didnt do that for some months so maybe there are already improvements.

Spaeda commented 3 years ago

Hi,

Any news about this point?

I try with Swashbuckle and UI manage multi files image

kodiKING10 commented 2 years ago

Different from Swashbuckle, NSwag still can't handle multiple files, this is the issue opened in swashbuckle https://github.com/domaindrivendev/Swashbuckle.AspNetCore/issues/1029, this needs to be fixed asap.

mm3141 commented 2 years ago

Do we need to update Swagger UI 3 in NSwag.AspNetCore? Didnt do that for some months so maybe there are already improvements.

Looks like it has been fixed here: https://github.com/swagger-api/swagger-ui/releases/tag/v3.26.0

n0one42 commented 7 months ago

I also have still the same problem. public async Task<IResult> MyPostCall(HttpRequest request, ISender sender, [FromForm] List<IFormFile> files) I have to use [FromForm] List<IFormFile> to get the Choose File Button. Otherwise it does not appear but files remains empty while the request.Form.Files contains the uploaded files.

I also tried IFormFileCollection but this also does not work.

My only solution to get the Choose File button is to implement the not filled List and handling the request.Form.Files

files = request.Form.Files.ToList();