Flask - 获取请求中每个文件的大小?

时间:2014-02-28 20:36:44

标签: python request flask

我在网站上传,并使用flask作为后端。这些文件都是在一个POST请求中从客户端发送到服务器的,我正在使用getlist()的{​​{1}}方法单独处理它们,并使用for循环迭代:

request

问题是我想限制上传到50mb的EACH文件的大小,但我假设if request.method == 'POST': files = request.files.getlist('f[]') 限制了整个请求的大小。有没有办法可以评估MAX_CONTENT_LENGTH对象中每个文件的大小,如果文件太大,就拒绝该文件?用户可以上传一定数量的文件,但每个文件需要不超过50mb。

2 个答案:

答案 0 :(得分:3)

您可以在此处使用两条信息:

  1. 有时会设置Content-Length标头;解析确保这对于上载的实际数据是准确的。如果是这样,您可以从FileStorage.content_length attribute获取此值。

  2. 上传的文件是文件对象(磁盘上的临时文件或类似内存文件的对象);只需在这些上使用file.seek()file.tell()即可确定其大小,而无需阅读整个对象。 可能是内存中的文件对象不支持搜索,此时你应该能够将整个文件读入内存,因为它足够小而不需要临时-disk文件。

  3. 结合起来,测试单个文件大小的最佳方法是:

    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
    

    然后在你的循环中:

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

    这避免了必须完全将数据读入内存。

答案 1 :(得分:-3)

将MAX_CONTENT_LENGTH设置为适合所有文件总大小的值,然后在处理之前检查每个文件的文件大小。

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