Reputation: 1056
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.
Upvotes: 4
Views: 6663
Reputation: 1121296
There are two pieces of information you can use here:
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.
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.
Upvotes: 7
Reputation: 4643
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
Upvotes: -4