dpgaspar / Flask-AppBuilder

Simple and rapid application development framework, built on top of Flask. includes detailed security, auto CRUD generation for your models, google charts and much more. Demo (login with guest/welcome) - http://flaskappbuilder.pythonanywhere.com/
BSD 3-Clause "New" or "Revised" License
4.67k stars 1.36k forks source link

Uploads pain points #1114

Open CameronNemo opened 5 years ago

CameronNemo commented 5 years ago

If you'd like to report a bug in Flask-Appbuilder, fill out the template below. Provide any extra information that may be useful

Environment

Flask-Appbuilder version: 2.1.13

pip freeze output:

alembic==1.1.0
apispec==1.3.3
attrs==19.1.0
Babel==2.7.0
certifi==2019.3.9
chardet==3.0.4
Click==7.0
colorama==0.4.1
defusedxml==0.6.0
Flask==1.1.1
Flask-AppBuilder==2.1.13
Flask-Babel==0.12.2
Flask-JWT-Extended==3.22.0
Flask-Login==0.4.1
Flask-Migrate==2.5.2
Flask-OpenID==1.2.5
Flask-SQLAlchemy==2.4.0
Flask-WTF==0.14.2
idna==2.8
itsdangerous==1.1.0
Jinja2==2.10.1
jsonschema==3.0.2
Mako==1.1.0
MarkupSafe==1.1.1
marshmallow==2.19.5
marshmallow-enum==1.5.1
marshmallow-sqlalchemy==0.19.0
Pillow==6.1.0
prison==0.1.2
pyasn1==0.4.7
pyasn1-modules==0.2.6
PyJWT==1.7.1
pyrsistent==0.15.4
python-dateutil==2.8.0
python-editor==1.0.4
python-ldap==3.2.0
python3-openid==3.1.0
pytz==2019.2
PyYAML==5.1.2
requests==2.22.0
six==1.12.0
SQLAlchemy==1.3.8
SQLAlchemy-Utils==0.34.2
urllib3==1.25.3
uWSGI==2.0.18
Werkzeug==0.15.6
WTForms==2.2.1

Describe the expected results

  1. When using a non-existent directory for the uploads folder, the folder should be created with the executable bits set. Otherwise, flask-appbuilder will become unable to save files in said folder. I am having to manually set those permissions, even though I theoretically should not need to.

  2. When specifying the path for the uploads folder without a trailing slash, flask-appbuilder fails to correctly provide the URL for files. Perhaps a strategic call to os.path.join could alleviate this issue.

sep 10 09:54:10 pgndb.tus.cenic.org docker[7449]: 2019-09-10 16:54:10,449:ERROR:app:Exception on /attachmentview/download/6b91ba4a-d3e9-11e9-a0a7-0242ac110003_sep_cat5172.jpg [GET]
sep 10 09:54:10 pgndb.tus.cenic.org docker[7449]: Traceback (most recent call last):
sep 10 09:54:10 pgndb.tus.cenic.org docker[7449]: File "/usr/local/lib/python3.7/site-packages/flask/app.py", line 2446, in wsgi_app
sep 10 09:54:10 pgndb.tus.cenic.org docker[7449]: response = self.full_dispatch_request()
sep 10 09:54:10 pgndb.tus.cenic.org docker[7449]: File "/usr/local/lib/python3.7/site-packages/flask/app.py", line 1951, in full_dispatch_request
sep 10 09:54:10 pgndb.tus.cenic.org docker[7449]: rv = self.handle_user_exception(e)
sep 10 09:54:10 pgndb.tus.cenic.org docker[7449]: File "/usr/local/lib/python3.7/site-packages/flask/app.py", line 1820, in handle_user_exception
sep 10 09:54:10 pgndb.tus.cenic.org docker[7449]: reraise(exc_type, exc_value, tb)
sep 10 09:54:10 pgndb.tus.cenic.org docker[7449]: File "/usr/local/lib/python3.7/site-packages/flask/_compat.py", line 39, in reraise
sep 10 09:54:10 pgndb.tus.cenic.org docker[7449]: raise value
sep 10 09:54:10 pgndb.tus.cenic.org docker[7449]: File "/usr/local/lib/python3.7/site-packages/flask/app.py", line 1949, in full_dispatch_request
sep 10 09:54:10 pgndb.tus.cenic.org docker[7449]: rv = self.dispatch_request()
sep 10 09:54:10 pgndb.tus.cenic.org docker[7449]: File "/usr/local/lib/python3.7/site-packages/flask/app.py", line 1935, in dispatch_request
sep 10 09:54:10 pgndb.tus.cenic.org docker[7449]: return self.view_functions[rule.endpoint](**req.view_args)
sep 10 09:54:10 pgndb.tus.cenic.org docker[7449]: File "/usr/local/lib/python3.7/site-packages/flask_appbuilder/security/decorators.py", line 123, in wraps
sep 10 09:54:10 pgndb.tus.cenic.org docker[7449]: return f(self, *args, **kwargs)
sep 10 09:54:10 pgndb.tus.cenic.org docker[7449]: File "/usr/local/lib/python3.7/site-packages/flask_appbuilder/views.py", line 610, in download
sep 10 09:54:10 pgndb.tus.cenic.org docker[7449]: as_attachment=True,
sep 10 09:54:10 pgndb.tus.cenic.org docker[7449]: File "/usr/local/lib/python3.7/site-packages/flask/helpers.py", line 629, in send_file
sep 10 09:54:10 pgndb.tus.cenic.org docker[7449]: file = open(filename, "rb")
sep 10 09:54:10 pgndb.tus.cenic.org docker[7449]: FileNotFoundError: [Errno 2] No such file or directory: '/var/lib/pgndb/uploads6b91ba4a-d3e9-11e9-a0a7-0242ac110003_sep_cat5172.jpg'
sep 10 09:54:10 pgndb.tus.cenic.org docker[7449]: [pid: 1|app: 0|req: 208/208] 137.164.83.123 () {42 vars in 1322 bytes} [Tue Sep 10 16:54:10 2019] GET /attachmentview/download/6b91ba4a-d3e9-11e9-a0a7-0242ac110003_sep_cat5172.jpg => generated 290 bytes in 40 msecs (HTTP/1.1 500) 4 headers in 517 bytes (1 switches on core 0)

I am working around the trailing slash issue below:

diff --git a/config.py b/config.py
index 56b6acb..d08bdd6 100644
--- a/config.py
+++ b/config.py
@@ -5,7 +5,7 @@ basedir = os.getenv('PGNDB_BASEDIR', '/var/lib/pgndb')

 SQLALCHEMY_DATABASE_URI = 'sqlite:///' + os.path.join(basedir, 'app.db')
 # file upload folder, when using models with files
-UPLOAD_FOLDER = os.path.join(basedir, 'uploads')
+UPLOAD_FOLDER = basedir + '/uploads/'
 # image upload folder, when using models with images
 IMG_UPLOAD_FOLDER = UPLOAD_FOLDER
 # image upload url, when using models with images
dpgaspar commented 5 years ago

Looks good, I'll update the examples