python - 使用 Bottle (或 flask 或类似物)流式上传文件

标签 python rest file-upload bottle

我有一个使用 Python/Bottle 编写的 REST 前端,它处理文件上传,通常是大文件。 API 的编写方式如下:

客户端将文件作为负载发送 PUT。除其他外,它发送日期和授权 header 。这是一种针对重放攻击的安全措施——请求使用临时 key 、目标 url、日期和其他一些内容进行签名

现在是问题。如果提供的日期在给定的 15 分钟日期时间窗口内,则服务器接受请求。如果上传时间足够长,它将比允许的时间增量长。现在,请求授权处理是在 bottle view 方法上使用装饰器完成的。但是,除非上传完成,否则 Bottle 不会开始发送过程,因此对于较长的上传,验证会失败。

我的问题是:有没有办法向 Bottle 或 WSGI 解释立即处理请求并在上传时流式传输?出于其他原因,这对我也很有用。或任何其他解决方案?在我写这篇文章时,我想到了 WSGI 中间件,但我仍然想要外部洞察力。

我愿意切换到 Flask,甚至是其他 Python 框架,因为 REST 前端非常轻量级。

谢谢

最佳答案

我建议在前端将传入文件拆分为更小的 block 。我这样做是为了在 Flask 应用程序中实现大文件上传的暂停/恢复功能。

使用 Sebastian Tschan's jquery plugin ,您可以通过在初始化插件时指定 maxChunkSize 来实现分 block ,如:

$('#file-select').fileupload({
    url: '/uploads/',
    sequentialUploads: true,
    done: function (e, data) {
        console.log("uploaded: " + data.files[0].name)
    },
    maxChunkSize: 1000000 // 1 MB
});

现在客户端在上传大文件时会发送多个请求。您的服务器端代码可以使用 Content-Range header 将原始大文件修补在一起。对于 Flask 应用程序, View 可能类似于:

# Upload files
@app.route('/uploads/', methods=['POST'])
def results():

    files = request.files

    # assuming only one file is passed in the request
    key = files.keys()[0]
    value = files[key] # this is a Werkzeug FileStorage object
    filename = value.filename

    if 'Content-Range' in request.headers:
        # extract starting byte from Content-Range header string
        range_str = request.headers['Content-Range']
        start_bytes = int(range_str.split(' ')[1].split('-')[0])

        # append chunk to the file on disk, or create new
        with open(filename, 'a') as f:
            f.seek(start_bytes)
            f.write(value.stream.read())

    else:
        # this is not a chunked request, so just save the whole file
        value.save(filename)

    # send response with appropriate mime type header
    return jsonify({"name": value.filename,
                    "size": os.path.getsize(filename),
                    "url": 'uploads/' + value.filename,
                    "thumbnail_url": None,
                    "delete_url": None,
                    "delete_type": None,})

对于您的特定应用程序,您只需确保正确的身份验证 header 仍随每个请求一起发送。

希望对您有所帮助!我在这个问题上苦苦挣扎了一段时间;)

关于python - 使用 Bottle (或 flask 或类似物)流式上传文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15040706/

相关文章:

python - 更改 docker-compose 文件中 docker 容器中的 PYTHONPATH

python - 如何在 python pandas 中将标题行转换为新列?

python - 在Azure中使用python获取角色分配列表

php - 如何从使用 Paypal rest-api-sdk-php 库完成的请求中获取 token

mysql - node express mysql 驱动程序插入操作错误

php - 如何使用隐藏的 iframe + jquery 进行文件上传?

javascript - 使用 Angular 4上传文件

python - 如何在Python中对顺序数据的虚拟变量进行编码,以便始终保持相同的顺序?

javascript - 如何使用 RESTful URI 在 javascript 中发出 Get 请求?

php - 通过浏览器上传大文件(100 GB)