connexion icon indicating copy to clipboard operation
connexion copied to clipboard

Multiple files upload (mutlipart/form-data) is ignored for Flask

Open kornicameister opened this issue 6 years ago • 15 comments

Description

Consider following endpoint definition:

  /test-formData-file-upload:
    post:
      summary: 'Test formData with file type, for file upload'
      operationId: fakeapi.hello.test_formdata_file_upload
      responses:
        '200':
          description: OK
      requestBody:
        content:
          multipart/form-data:
            schema:
              x-body-name: formData
              type: object
              properties:
                formData:
                  type: array
                  items:
                    type: string
                    format: binary
              required:
                - formData

What we are doing in here is uploading multiple files from the same mulipart field. That gets correctly pulled from flask_request but ignored later in connexion.operations.abstract.AbstractOperation#_get_file_arguments

Expected behaviour

Request to Flask-based application with multiple files is correctly processed and we get multiple files available inside of handler.

Actual behaviour

Multiple files are ignored, only first is taken into account.

Steps to reproduce

  1. open connexion/tests/fixtures/simple/openapi.yaml
  2. find /test-formData-file-upload definition
  3. Use snippet from above to replace the definition
  4. Go to tests.api.test_parameters.test_formdata_file_upload
  5. Use following code to replace the function
def test_formdata_file_upload(simple_app):
    app_client = simple_app.app.test_client()
    resp = app_client.post('/v1.0/test-formData-file-upload',
                           data={'formData': [(BytesIO(b'file contents'), 'filename1.txt'), (BytesIO(b'file contents'), 'filename2.txt')]})
    assert resp.status_code == 200
    response = json.loads(resp.data.decode('utf-8', 'replace'))
    assert response == {'filename1.txt': 'file contents'}
  1. Observe test to pass, which it should not do.

Additional info:

Output of the commands:

  • python --version -> 3.7.3
  • pip show connexion | grep "^Version\:" -> master branch
  • flask --version -> 1.1.0

kornicameister avatar Jul 08 '19 06:07 kornicameister

cc @dtkav @hjacobs

kornicameister avatar Jul 08 '19 06:07 kornicameister

Looks like a duplicate of #510. You can see my fork here https://github.com/simondrabble/connexion for a fix.

simondrabble avatar Jul 19 '19 17:07 simondrabble

I think this is closed by #1000 Please re-open if there's something I missed.

dtkav avatar Nov 10 '19 17:11 dtkav

I think this is closed by #1000 Please re-open if there's something I missed.

https://github.com/zalando/connexion/pull/1000 was reverted in https://github.com/zalando/connexion/pull/1101 because it broke httpaio backend

I think this is being followed in https://github.com/zalando/connexion/pull/987

Kindly bumping :) I could use Flask multipart file upload, perhaps this issue should be reopened?

guillaumedsde avatar Dec 15 '19 16:12 guillaumedsde

What is the status of this issue? Can we expect to have the possibility to perform multiple files uploads or should we choose another framework? It is indeed related to #987, which seems to be slightly updated though.

swan001 avatar Jan 29 '20 16:01 swan001

status?

dfeinzeig avatar May 20 '20 16:05 dfeinzeig

@dfeinzeig it looks like its being worked on here if you want to check it out :wink: : https://github.com/zalando/connexion/pull/1222

guillaumedsde avatar May 20 '20 20:05 guillaumedsde

@kornicameister, I know it's been a while, but would you mind checking if either master or my PR #1222 fixes your issue? Do you still have what's needed to check it?

Thanks

ddurham2 avatar May 22 '20 04:05 ddurham2

hey @ddurham2 I do not have any project setup available, that project is long gone.

My only suggestion to actually verify that would be to write extensive test that loads bunch of files, sends them and you are trying to read them, but this is exactly what you have done. I think that if you manage to write really decent test coverage, it ill be proof enough to verify your PR ;-)


I have left some suggestions in PR.

kornicameister avatar May 22 '20 05:05 kornicameister

You can get the files from connexion.request.files.getlist('formData')

p10ns11y avatar Dec 02 '20 10:12 p10ns11y

Bumping it up. It would be very helpful to have multiple files upload out of the box. Waiting for #1222 to be merged : )

rafspiny avatar May 28 '21 08:05 rafspiny

closable by my account

ddurham2 avatar Feb 18 '22 23:02 ddurham2

@ddurham2 this has been fixed for aiohttp, but not flask. I tested the provided example to be sure.

RobbeSneyders avatar Feb 19 '22 10:02 RobbeSneyders

@RobbeSneyders, while I don't utilize flask in any projects, I'd be willing to take a stab at it if you thought it was worth it... Do the flask-based unit tests run by default? I'd guess the procedure would be to add a unit tests that reproduces the problem and then make fixes from there. Otherwise, I can leave it alone.

ddurham2 avatar Feb 19 '22 18:02 ddurham2

Sounds good @ddurham2. We should be able to reuse #1000, which includes a test, but still need to resolve the same issue that caused it to be reverted in #1101. The implementation uses request.files.getlist() which works for Flask since request.files is a MultiDict there, but fails for aiohttp since files is a normal dict there.

RobbeSneyders avatar Feb 19 '22 18:02 RobbeSneyders