It is still not clear for me when to use send_file
and when send_from_directory
.
I have a file in a folder protected. I can access the file from both methods. So perhaps someone has an example that makes clear which function should be used.
@app.route('/sfile/<id>') def sfile(id=None): try: return send_file('protected/'+id, attachment_filename='python.jpg') except: return('') @app.route('/sdir/<path:filename>') def sdir(filename): try: return send_from_directory( os.path.join(app.instance_path, ''), filename ) except: return ''
send_from_directory (directory, filename, **options)[source] Send a file from a given directory with send_file() . This is a secure way to quickly expose static files from an upload folder or something similar.
send_file transfers the contents of a file to the client using the most efficient method available and configured in the Flask settings. It attempts to guess the correct mimetype to use but it can also be explicitly configured. Note that send_file is usually imported directly from flask instead of from flask.
Flask – File Uploading Handling file upload in Flask is very easy. It needs an HTML form with its enctype attribute set to 'multipart/form-data', posting the file to a URL. The URL handler fetches file from request. files[] object and saves it to the desired location.
join function to append the Flask app's root path stored in current_app. root_path and the upload folder's path from the root folder stored in app. config['UPLOAD_FOLDER'] . current_app is the application context.
send_file
is the function that handles sending files to the user. It does no sanity check on the input, so it would also happily send protected/../../../etc/passwd
or whatever. In your specific case that might not work, but if you are unaware of that type of attack you might produce unsecure code.
send_from_directory
checks wether the requested file is really from the specified directory. That way the above attack would not work.
So you can use send_file
whenenver the input filepath is trusted. That means either do your own checks or if the input is provided by you (e.g. my_file_paths = {"a": "path/to/a", ... }; send_file(my_file_paths[user_input])
would be okay) you should be fine. For the common case send_from_directory
is a helper function that does the appropriate security checks.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With