Nswag: Multiple file upload via UI

Created on 27 Jun 2018  路  15Comments  路  Source: RicoSuter/NSwag

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];
      }
NSwag.AspNetCore swagger-ui bug

Most helpful comment

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

All 15 comments

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?

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.

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" }

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

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

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 {
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

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

I have the same problem. Any updates???

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

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

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

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

I think so, yes...

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!

I confirm that:

  • Swagger UI 3 sends files array as [object File] <-- which makes ASP.NET Core request.Form.Files getting no files on controller side.
curl -X POST "http://localhost:5000/api/attachments" -H "accept: application/json" -H "Authorization: Bearer eyJ...trimmed..." 
-H "Content-Type: multipart/form-data" -F "StructureId=14" -F "Description=dsgf" -F "Files=[object File]" 
  • Open API schema looks good and generates correct TypeScript code (the only thing I had to adjust was mapping form files to to objects of FileParameter - code snippet is below as well) which works fine.
"/api/attachments": {
      "post": {
        "tags": [           "Attachments"         ],
        "operationId": "Attachments_AttachStructureFile",
        "requestBody": {
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "properties": {
                  "StructureId": {                     "type": "integer",                    "format": "int32"                  },
                  "Description": {                    "type": "string",                    "nullable": true                  },
                  "Files": {
                    "type": "array",
                    "nullable": true,
                    "items": {
                      "type": "string",
                      "format": "binary"
                    }
                  },
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "", 
            "content": {
              "application/json": {
                "schema": {                  "$ref": "#/components/schemas/SipAttachStructureFileResponse"                }
              }
            }
          }
        },
        "security": [          {            "JWT": []          }        ]
      }
    }

What I use:

  • NSwag.AspNetCore v 13.7.0 (package in API project which is used to generate OpenAPI spec for Swagger UI 3)
  • NSwagStudio (x64) 13.7.0.0 (this what I use to generate TS client)

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

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

Was this page helpful?
0 / 5 - 0 ratings