From 1a21390ba6b771c16e09185eef567bff77d23958 Mon Sep 17 00:00:00 2001 From: Justin Ehlert Date: Wed, 14 Feb 2018 08:58:04 -0600 Subject: [PATCH] Fix handling of multi-value file fields Some clients (e.g. Swagger), rather than specifying `file1`, `file2`, etc... will specify multiple values for `file` when uploading multiple files. This code change will handle lists of values for individual fields. --- api/upload.py | 20 +++++++++++++++---- .../integration_tests/python/test_uploads.py | 7 ++++++- 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/api/upload.py b/api/upload.py index 617a30355..75de2e470 100644 --- a/api/upload.py +++ b/api/upload.py @@ -91,16 +91,13 @@ def process_upload(request, strategy, container_type=None, id_=None, origin=None # Here, we accept any # Non-file form fields may have an empty string as filename, check for 'falsy' values - file_fields = [x for x in form if form[x].filename] + file_fields = extract_file_fields(form) # TODO: Change schemas to enabled targeted uploads of more than one file. # Ref docs from placer.TargetedPlacer for details. if strategy == Strategy.targeted and len(file_fields) > 1: raise FileFormException("Targeted uploads can only send one file") - - for field in file_fields: - field = form[field] # Augment the cgi.FieldStorage with a variety of custom fields. # Not the best practice. Open to improvements. # These are presumbed to be required by every function later called with field as a parameter. @@ -270,3 +267,18 @@ def clean_packfile_tokens(self): 'directories': cleaned, } } + +def extract_file_fields(form): + """Returns a list of file fields in the form, handling multiple values""" + result = [] + for fieldname in form: + field = form[fieldname] + if isinstance(field, list): + for field_entry in field: + if field_entry.filename: + result.append(field_entry) + + elif field.filename: + result.append(field) + + return result diff --git a/tests/integration_tests/python/test_uploads.py b/tests/integration_tests/python/test_uploads.py index e17a9dbfb..d97fa8b8b 100644 --- a/tests/integration_tests/python/test_uploads.py +++ b/tests/integration_tests/python/test_uploads.py @@ -1197,9 +1197,14 @@ def test_packfile_upload(data_builder, file_form, as_admin, as_root, api_db): assert r.ok token = r.json()['token'] + files = [ + ('file', file_form('two.csv')['file']) , + ('file', file_form('three.csv')['file']) + ] + # upload to packfile r = as_admin.post('/projects/' + project + '/packfile', - params={'token': token}, files=file_form('two.csv')) + params={'token': token}, files=files) assert r.ok # expire upload token