noirbizarre / flask-restplus

Fully featured framework for fast, easy and documented API development with Flask
http://flask-restplus.readthedocs.org
Other
2.73k stars 507 forks source link

FileUpload with required=True #463

Open hhllcks opened 6 years ago

hhllcks commented 6 years ago

Hi,

it seems that using the parameter required=True for a FileUpload like it is shown in the documentation does not seem to work. If the parameter is set, I get the following error:

{
  "errors": {
    "file": "Missing required parameter in an uploaded file"
  },
  "message": "Input payload validation failed"
}

If the parameter is not there, everything works fine.

I am using Flask 1.0.2 and Flask_restplus 0.11.0.

Here is the full code of my example:

from flask import Flask, Response, jsonify, request
from flask_restplus import Api, Resource
from flask_cors import CORS 
from werkzeug.datastructures import FileStorage

app = Flask(__name__) 
CORS(app) 
api = Api(app, version='1.0', title='My API', validate=False)

upload_parser = api.parser()
upload_parser.add_argument('file', location='files', type=FileStorage, required=True)

@api.route('/upload')
@api.expect(upload_parser)
class Upload(Resource):
    def post(self):
        args = upload_parser.parse_args()
        uploaded_file = args['file']  # This is FileStorage instance
        print(list(args.keys()))
        # url = do_something_with_file(uploaded_file)
        return {'Hello': 'File'}, 201

if __name__ == '__main__': 
    app.run(host='0.0.0.0', debug=True)
hhllcks commented 6 years ago

It seems that my problem could lie somewhere else. It seems that the swagger ui does not upload the files correctly.

If you curl myself like this everything works fine:

curl -X POST "http://localhost:5000/upload" -H "accept: application/json" -F "file=@5.png"

The questions is then: why does swagger ui create a curl call that looks like this:

curl -X POST "http://localhost:5000/digit" -H "accept: application/json" -H "Content-Type: application/json" -d {"file":{}}

Why does it want to send it as json?

floschne commented 6 years ago

I'm experiencing the exact same error. And I also think that the problem is on the SwaggerUI part of flask-restplus since it generates this wrong curl call.. Please solve this issue since it's very annoying to upload the file per terminal and then test the rest of the API in the SwaggerUI I build a WebApp where I upload the file from a standard HTML Form and it works perfectly fine.

SimonVerhoek commented 6 years ago

+1 here. Currently using Postman as a workaround (as described here) . Would love to see this solved as well!

liviaalmeida commented 6 years ago

+1, also facing the same problem

pk8189 commented 5 years ago

+1 same problem

Sanix-Darker commented 5 years ago

+1 same problem

romulofff commented 5 years ago

Does anyone found a solution to this? Same problem here

gaurav02712 commented 4 years ago

issue was genrated in june 2018 and we are still facing this issue.

dsp85103 commented 4 years ago

This is my code in my case, I use reqparse from flask_restplus parser.py

import werkzeug
from flask_restplus import reqparse

image_upload = reqparse.RequestParser()
image_upload.add_argument('propic',
                          type=werkzeug.datastructures.FileStorage,
                          location='files',
                          required=True,
                          help='Image file cannot empty')

image_resource.py

    @namespace_user.expect(parser.image_upload)  #namespace maybe could change to api from flask_restplus
    def put(self):
        output = {}
        img_arg = 'propic'
        args = parser.image_upload.parse_args()
        if args[img_arg].mimetype == 'multipart/form-data' or args[img_arg].mimetype == 'image/png':
            data_user_propics_path = 'data/propics/'
            destination = os.path.join(os.path.dirname(os.path.abspath(__file__)),data_user_propics_path)

            if not os.path.exists(destination):
                os.makedirs(destination)

            img_hash_filename = hash_filename_by_md5("something_what_you_want")
            img_file = '%s%s' % (destination, img_hash_filename)

            try:
                args[img_arg].save(img_file)

                return make_response(jsonify({
                    'url': img_file
                }), 201)

            except Exception as e:

                print(e)
                return make_response(jsonify({
                    'message': 'image storage error'
                }), 500)

        else:
            return make_response(jsonify({
                'message': 'image type error'
            }), 401)

and it's work fine.

wbqtac commented 3 years ago

also meet the same problem, any work around?

mdylan2 commented 2 years ago

Any update on this issue? Facing the same problem here

g5539220y commented 2 years ago

When making a front-end request, try to remove the header configuration and keep the default header