Filestorage python flask read

Explanation¶

UploadSet is the main object provided by the FlaskReuploaded extension. Each UploadSet is responsible for dealing with a set of files. You have to initialize UploadSet by calling its constructor and passing it the required first parameter name :

photos = UploadSet(name='photos', extensions=IMAGES) 

The second parameter is optional extensions iterable. For your convenience, there are ready-to-use extensions you can import from flask_uploads.extensions . The third parameter is the default_dest callable that will be discussed later.

After initializing the UploadSet , you have to call configure_uploads function that builds the UploadConfiguration and stores it on the application instance.

Now, your UploadSet ’s are configured, you can use the UploadSet.save method to save uploaded files and the UploadConfiguration to serve them.

During saving and serving the uploaded files, the UploadSet object performs some security checks for you.

Security Checks¶

Security itself is a huge subject and you should consider designing it seriously. The Flask-Reuploaded extension tries to help you by preventing some common attack vectors and user errors. For example:

  • Users can’t upload files with filenames that start with dot . for example:
    1. ‘.’
    2. ‘..’
    3. ‘../../../home//.bash’
    4. ‘../../my_app.wsgi’

if a user tries to upload a file with such a filename, the file will be renamed.

  • Users can’t overwrite other users’ files, i.e., similar filenames are suffixed by a number .
  • Users can’t upload files with extension suffixes that are not allowed by the UploadSet .
Читайте также:  Php get img url

You are advised to read the source code to explore the mechanism of dealing with each error/attack, and you may decide to take additional actions.

Maximum Allowed File Size¶

Another security aspect that you should consider is the maximum allowed file size. This is NOT managed by the Flask-Reuploaded extension.

By default, the Flask application will accept file uploads of any length. It is up to your server to save the uploaded file or fill your hard drive till raising No space left on device error. You can (obviously, you should) set the maximum allowed file length by setting the MAX_CONTENT_LENGTH configuration. After this, Flask will reject files that are larger than this limit.

This alone may not be enough. As uploading a thousand files of 10 MB in size may also cause your server to crash. This aspect is outside of the scope of this extension but worth mentioning here.

Configuring the destination for the UploadSet ¶

Each UploadSet object should know its destination path to store the uploaded files in. When you call the configure_uploads function, the UploadSet object tries to set its destination path following this order:

  • UPLOADED_[1]_DEST where is [1] is the capitalized name of the UploadSet
  • The return value of the :ref: default_dest if present
  • Subdirectory in the UPLOADS_DEFAULT_DEST if present. The name of the subdirectory is the same name of the UploadSet

If all these trials failed, a RuntimeError will be raised.

default_dest ¶

The UploadSet constructor can accept a default_dest parameter. It is a callable that takes the application as its argument and returns the destination path for this set.

..code-block:: python def set_destination(app): return os.path.join(app.instance_path, "uploads") media = UploadSet('media', default_dest=set_destination ) 

This will save your uploads in the /uploads .

configure_uploads ¶

You have to call the configure_uploads function after the app has been configured. The configure_uploads function is responsible for creating the UploadConfiguration ’s and storing them on the application instance.

The configure_uploads function accepts two parameters. The first is the Flask application instance and the second is either an UploadSet instance or iterable of UploadSet instances. It is safe to call the configure_uploads function more than once.

The configure_uploads function sets upload_set_config attribute on the application instance. It is a dictionary of UploadSet names mapped to their corresponding UploadConfiguration objects. This way, you are able to get the UploadConfiguration in your view functions from current_app.upload_set_config[‘setname’] when you need to serve the files, see Serving Files .

Multithreaded Application¶

As mentioned, the :ref: configure_uploads function stores the UploadSet ’s configuration on the application instance itself. That way, you can have UploadSet being used by multiple applications that run in different threads. . If your application has a factory function, that is a good place to call it.

from flask_uploads import configure_uploads def init_app(): . configure_uploads(app, (photos, media)) . return app 

Saving Files¶

When you upload a file, you should call the UploadSet.save method. This method accepts a werkzeug.datastructures.FileStorage object as its first parameter. Any object with another type will raise TypeError . You can get a werkzeug.datastructures.FileStorage object by accessing the flask.request.files dictionary.

The UploadSet.save method accepts optional parameter folder . If given, the uploaded file will be saved in UploadSet.destination/folder subdirectory.

The third optional parameter is the name . If given, the UploadSet will use this value instead of the value of the werkzeug.datastructures.FileStorage.filename .

Note that you can include the folder in the name parameter instead of explicitly using folder , i.e. uset.save(file, name=»someguy/photo_123.»)

By using the folder and name parameters, You can achieve complete control of the saved files within the UploadSet . As an example: you can store each user files in a separate directory.

The UploadSet.save method returns the saved filename. Note that this isn’t always equal to the filename uploaded by the user nor the name parameter you passed. As mentioned in Security Checks , the Flask-Reuploaded extension might rename the uploaded file in certain circumstances. Also, if you pass the folder parameter the return value will be a relative path to the UploadSet destination.

Usually, you are expected to store the return value of the UploadSet.save method in order to use it for serving the uploaded file later.

File Upload Forms¶

To actually upload the files, you need to properly set up the HTTP requests. You must obtain a werkzeug.datastructures.FileStorage by using the flask.request.files[‘field_name’] .

Unfortunately, the flask.request.files[‘field_name’] may be empty if your request is misconfigured. As declared by Flask:

Note that files will only contain data if the request method was POST, PUT or PATCH and the that posted to the request had enctype=”multipart/form-data”. It will be empty otherwise.

This means that if the request method is GET , it won’t work at all, and if you don’t set the enctype, only the filename will be transferred.

The field in the HTML form itself should be an . For example:

form method=POST enctype=multipart/form-data action=" <url_for('upload') >>"> . input type='file' name='photo'>  . form> 

If you are using a client other than the browser, you should configure your request manually to implement the Flask’s requirements.

Serving Files¶

When you upload a file using the Flask-Reuploaded extension, you call the UploadSet.save method. This method returns the saved filename or path. You are expected to store the UploadSet name and the UploadSet.save return value for serving the uploaded file.

To serve an uploaded file, use the UploadSet name to get the UploadConfiguration instance:

uploadset_config = current_app.upload_set_config.get(uploadset_name) 

If the uploadset_config is not None , you can pass its destination property as well as the saved filename to the flask.send_from_directory method to safely serve your file.

return send_from_directory(uploadset_config.destination, filename) 

Of course, you can use another method, but the send_from_directory is secure and it uses flask.send_file under the hood. Please take a look at the send_from_directory and send_file .

AutoServing Files¶

You can save time, you can set app.config[‘UPLOADS_AUTOSERVE’] to True . This will add _uploads.uploaded_file endpoint to your application. This endpoint requires two parameters, setname parameter, which should be equal to the UploadSet name; and the filename parameter, which is the saved filename or path, i.e., the return value of the UploadSet.save method.

Once you have these parameters, you can serve your uploaded files from this url:

url = url_for( "_uploads.uploaded_file", setname="photos", filename=filename ) 

Note that the UPLOADS_AUTOSERVE is True by default in Flask-Reuploaded

Table of Contents

Contents

  • Explanation
    • Upload Sets
    • Security Checks
    • Maximum Allowed File Size
    • Configuring the destination for the UploadSet
    • default_dest
    • configure_uploads
    • Multithreaded Application
    • Saving Files
    • File Upload Forms
    • Serving Files
    • AutoServing Files

    © Copyright Matthew «LeafStorm» Frazier, Jürgen Gmach. Last updated on 2023-07-11. Created using Sphinx 5.3.0.

    Источник

    Read file data without saving it in Flask

    FileStorage contains stream field. This object must extend IO or file object, so it must contain read and other similar methods. FileStorage also extend stream field object attributes, so you can just use file.read() instead file.stream.read() . Also you can use save argument with dst parameter as StringIO or other IO or file object to copy FileStorage.stream to another IO or file object.

    If you want to use standard Flask stuff — there’s no way to avoid saving a temporary file if the uploaded file size is > 500kb. If it’s smaller than 500kb — it will use «BytesIO», which stores the file content in memory, and if it’s more than 500kb — it stores the contents in TemporaryFile() (as stated in the werkzeug documentation). In both cases your script will block until the entirety of uploaded file is received.

    The easiest way to work around this that I have found is:

    1) Create your own file-like IO class where you do all the processing of the incoming data

    2) In your script, override Request class with your own:

    class MyRequest( Request ): def _get_file_stream( self, total_content_length, content_type, filename=None, content_length=None ): return MyAwesomeIO( filename, 'w' )

    3) Replace Flask’s request_class with your own:

    app.request_class = MyRequest

    I was trying to do the exact same thing, open a text file (a CSV for Pandas actually). Don’t want to make a copy of it, just want to open it. The form-WTF has a nice file browser, but then it opens the file and makes a temporary file, which it presents as a memory stream. With a little work under the hood,

    form = UploadForm() if form.validate_on_submit(): filename = secure_filename(form.fileContents.data.filename) filestream = form.fileContents.data filestream.seek(0) ef = pd.read_csv( filestream ) sr = pd.DataFrame(ef) return render_template('dataframe.html',tables=[sr.to_html(justify='center, classes='table table-bordered table-hover')],titles = [filename], form=form) 

    Источник

Оцените статью