【问题标题】:Python bottle - How to upload media files without DOSing the serverPython 瓶 - 如何在不占用服务器的情况下上传媒体文件
【发布时间】:2014-05-15 09:22:05
【问题描述】:

我正在使用this question的答案并看到评论:

   raw = data.file.read() # This is dangerous for big files

如何在不这样做的情况下上传文件?到目前为止我的代码是:

@bottle.route('/uploadLO', method='POST')
def upload_lo():
    upload_dir = get_upload_dir_path()
    files = bottle.request.files
    print files, type(files)
    if(files is not None):
        file = files.file
        print file.filename, type(file)
        target_path = get_next_file_name(os.path.join(upload_dir, file.filename))
        print target_path
        shutil.copy2(file.read(), target_path)  #does not work. Tried it as a replacement for php's move_uploaded_file
    return None

给出这个输出:

127.0.0.1 - - [03/Apr/2014 09:29:37] "POST /uploadLO HTTP/1.1" 500 1418
Traceback (most recent call last):
  File "C:\Python27\lib\site-packages\bottle.py", line 862, in _handle
    return route.call(**args)
  File "C:\Python27\lib\site-packages\bottle.py", line 1727, in wrapper
    rv = callback(*a, **ka)
  File "C:\dev\project\src\mappings.py", line 83, in upload_lo
    shutil.copy2(file.read(), target_path)
AttributeError: 'FileUpload' object has no attribute 'read'

我正在使用 python bottle v.12、dropzone.min.js 和 mongodb。我也在使用这个教程:

http://www.startutorial.com/articles/view/how-to-build-a-file-upload-form-using-dropzonejs-and-php

【问题讨论】:

    标签: python bottle dropzone.js


    【解决方案1】:

    这称为“文件 slurping”:

    raw = data.file.read() 
    

    you don't want to do it(至少在这种情况下)。

    这是读取未知(可能很大)大小的二进制文件的更好方法:

    data_blocks = []
    
    buf = data.file.read(8192)
    while buf:
        data_blocks.append(buf)
        buf = data.file.read(8192)
    
    data = ''.join(data_blocks)
    

    如果累积大小超过某个阈值,您可能还想停止迭代。

    希望有帮助!


    第 2 部分

    您询问了有关限制文件大小的问题,所以这里有一个修改版本:

    MAX_SIZE = 10 * 1024 * 1024 # 10MB
    BUF_SIZE = 8192
    
    # code assumes that MAX_SIZE >= BUF_SIZE
    
    data_blocks = []
    byte_count = 0
    
    buf = f.read(BUF_SIZE)
    while buf:
        byte_count += len(buf)
    
        if byte_count > MAX_SIZE:
            # if you want to just truncate at (approximately) MAX_SIZE bytes:
            break
            # or, if you want to abort the call
            raise bottle.HTTPError(413, 'Request entity too large (max: {} bytes)'.format(MAX_SIZE))
    
        data_blocks.append(buf)
        buf = f.read(BUF_SIZE)
    
    data = ''.join(data_blocks)
    

    它并不完美,但它很简单,而且在 IMO 方面已经足够好了。

    【讨论】:

    • 8192 是某种标准吗(仍在阅读您链接的文档)?另外,由于我使用的js有一定的限制,我需要限制大小吗?
    • 不,8Kb 只是一个约定,因为这是磁盘块的大小(曾经?)。您可以在您的案例中使用任何(合理的)值。
    • 不确定您所说的“js ...有某种限制”是什么意思,但恕我直言,如果它不能保护自己免受大文件的影响,则该代码将被认为设计不佳。我将编辑我的答案以展示您如何做到这一点。
    • 哦,我只是说我使用的 js 看起来将文件的大小限制在几百毫克,但我会按照你的建议执行。谢谢!
    • Bottle 将文件上传存储在request.files 中作为FileUpload 实例,以及有关上传的一些元数据。 FileUpload 有一个非常方便的 save 方法,可以为您执行“文件 slurping”。虽然它不检查最大文件上传,但恕我直言,最好让 nginx 在前面执行这种限制检查。
    【解决方案2】:

    要添加到 ron.rothman 的出色答案...要修复您的错误消息,请尝试此操作

    @bottle.route('/uploadLO', method='POST')
    def upload_lo():
        upload_dir = get_upload_dir_path()
        files = bottle.request.files
    
        # add this line
        data = request.files.data
    
        print files, type(files)
    
        if(files is not None):
            file = files.file
            print file.filename, type(file)
            target_path = get_next_file_name(os.path.join(upload_dir, file.filename))
            print target_path
    
            # add Ron.Rothman's code
            data_blocks = []
            buf = data.file.read(8192)
            while buf:
                data_blocks.append(buf)
                buf = data.file.read(8192)
    
            my_file_data = ''.join(data_blocks)
            # do something with the file data, like write it to target
            file(target_path,'wb').write(my_file_data)
    
        return None
    

    【讨论】:

    • 谢谢!我今晚看看这是否有效!在您的#do something 评论中,用户是否必须等待某事完成。您通常会生成一个线程来处理该操作吗?
    • 不,我只是将其添加为占位符。我的建议是下面的行,即将它写入您的目标路径。乐于助人。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-11
    • 2020-08-31
    • 1970-01-01
    • 2016-12-01
    • 1970-01-01
    • 2013-10-17
    相关资源
    最近更新 更多