Question

I am having uploads on a site, and using flask as the back-end. The files are all sent in one POST request from the client to the server, and I'm handling them individually by using the getlist() method of request, and iterating through with a for loop:

if request.method == 'POST':
    files = request.files.getlist('f[]')

Problem is I want to limit the size of EACH file uploaded to 50mb, but I'm assuming MAX_CONTENT_LENGTH limits the size of the entire request. Is there a way I can evaluate the size of each individual file in the request object and reject that file if it is too large? The user can upload a set number of files, but each one of them needs to be under 50mb.

Was it helpful?

Solution 2

Set MAX_CONTENT_LENGTH to something reasonable for the total size of all files and then just check the file size for each file before processing.

if request.method == 'POST':
       files = request.files.getlist('f[]')
       for f in files:
          if len(f.read()) < (50 * 1024 * 1024):
                # do something

OTHER TIPS

There are two pieces of information you can use here:

  1. Sometimes the Content-Length header is set; parsing ensures that this is accurate for the actual data uploaded. If so, you can get this value from the FileStorage.content_length attribute.

  2. The files uploaded are file objects (either temporary files on disk or in-memory file-like objects); just use file.seek() and file.tell() on these to determine their size without having to read the whole object. It may be that an in-memory file object doesn't support seeking, at which point you should be able to read the whole file into memory as it'll be small enough not to need a temporary on-disk file.

Combined, the best way to test for individual file sizes then is:

def get_size(fobj):
    if fobj.content_length:
        return fobj.content_length

    try:
        pos = fobj.tell()
        fobj.seek(0, 2)  #seek to end
        size = fobj.tell()
        fobj.seek(pos)  # back to original position
        return size
    except (AttributeError, IOError):
        pass

    # in-memory file object that doesn't support seeking or tell
    return 0  #assume small enough

then in your loop:

for fobj in request.files.getlist('f[]'):
    if get_size(fobj) > 50 * (1024 ** 2):
        abort(413)  # request entity too large

This avoids having to read data into memory altogether.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top