flask-restx
flask-restx copied to clipboard
Upload list of files using restX + Swagger
Hey,
I'm trying to upload a list of files to my post method using the swaggerUI I am defining my input using RequestParser and add_argument method. Uploading one file works just fine, but once I'm adding 'action=append' to make it a list of files it doesn't work.
my code looks like this:
from flask_restx import Namespace, Resource, reqparse
from werkzeug.datastructures import FileStorage
upload_parser = reqparse.RequestParser()
upload_parser.add_argument('images', location='files',
type=FileStorage, required=True, action="append")
@api.route("/")
class MyResource(Resource):
@api.expect(upload_parser)
def post(self):
args = upload_parser.parse_args()
images = args['images']
This is the cUrl from swagger:
curl -X POST "http://127.0.0.1:8000/" -H "accept: application/json" -H "Content-Type: application/x-www-form-urlencoded" -d "images=%5Bobject%20File%5D&images=%5Bobject%20File%5D"
And the problem is that swagger sends it as application/x-www-form-urlencoded
and not multipart/form-data
Saying again, if I don't add the action='append'
to the add_argument
method, and I only send one file using Swagger it sends it as multipart/form-data
Is there any way to control it?



Im also having this issue. It appears to be similar to this: https://github.com/noirbizarre/flask-restplus/issues/463 Quite annoying...
I tried forcing the content type with the decorator and the argument location as 'headers' as in the documentation but had the same issues as this issue: https://github.com/python-restx/flask-restx/issues/67
I Tried the same code and uploaded multiple files got to knew that if upload_parser.add_argument('images', location='files', type=FileStorage, required=True, action="append")
- If i use required=True then i am getting below error { "errors": { "file": "Missing required parameter in an uploaded file" }, "message": "Input payload validation failed" }
- If i remove the require=True, then i am getting None on the args class Upload(Resource): def post(self): args = upload_parser.parse_args() print(args, '&&&&&&&&') file = args.get('file') print(file.filename) return "Uploaded file is " + file.filename
output{'file': None} &&&&&&&& AttributeError: 'NoneType' object has no attribute 'filename'
Could anyone help me on this while uploading multiple files how to get the filenames and swagger documentation for that as well
I am also having the same problem... Was this never solved?
I think the problem is coming from the line https://github.com/python-restx/flask-restx/blob/af807aae3e18f70fc39a066d37f519cf32167efc/flask_restx/swagger.py#L469
It works when I replaced it by
if any(p["type"] == "file" or (p["type"] == "array" and p["items"]["type"]=="file") for p in all_params):
This actually does not seem to be supported in Swagger UI currently. See Swagger Docs and GitHub Issue. But it seems that it still works when submitting multiple files via other means, such as Postman. This is even without this patch.
Well, I do use Swagger UI to test my API, and my "patch" allows sending multiple files.
Maybe it does not work in all contexts...
I think the problem is coming from the line
https://github.com/python-restx/flask-restx/blob/af807aae3e18f70fc39a066d37f519cf32167efc/flask_restx/swagger.py#L469
It works when I replaced it by
if any(p["type"] == "file" or (p["type"] == "array" and p["items"]["type"]=="file") for p in all_params):
This solves the issue for me.
While it makes the Swagger UI look correct, it does not actually submit the files in the correct way though.
This is what it looks like recorded with Fiddler - just getting empty objects, and 2 files here are sent in the same key:
And this is what it should look like, files sent as file objects with the correct Content-Type
. Maybe the issue is just the missing Content-Type
?
When sent from a client other than swagger, the files do come through properly.
And also, when removing the action='append'
arg, the single file is sent correctly as well:
Indeed, not sure why it worked for a while... Closed the pull request the solution doesn't work.
Used for tests: main.py.txt
Any updates on this issue?
PR is still not approved. So you have to fork and merge for yourself
Thank you!
https://github.com/python-restx/flask-restx/pull/542 PR in for this issue, takes @jingapore solution slightly further resolving issues with list comprehensions for keys that do not always exist in the dict & corresponding unit test.