将Flask和S3用于大文件的首选方法

时间:2016-05-20 08:37:12

标签: python rest amazon-s3 flask flask-restful

我知道这有点开放,但我对使用 Flask和boto3 开发的大型文件上传服务的策略/方法感到困惑。对于较小的文件,一切都很好。但是当大小超过100 MB时,看到你们的想法真的很不错

我想到的是 -

  
    

a)使用某种AJAX上传器将文件传输到Flask应用程序(我正在尝试构建的只是使用Flask-Restful的REST接口。使用这些组件的任何示例,例如Flask-Restful,boto3和streaming large文件是受欢迎的。)上传应用程序将(我相信)是我们正在构建的微服务平台的一部分。我不知道烧瓶应用程序前面是否会有Nginx代理,或者它将直接从Kubernetes pod / service提供。如果它是直接提供的,我是否需要在kubernetes和/或Flask层中为大文件上传进行更改?

         

b)使用直接JS上传器(如http://www.plupload.com/)并直接将文件流式传输到s3存储桶中,完成后获取URL并将其传递给Flask API应用程序并将其存储在DB中。这个问题是,凭证需要存在于JS的某个地方,这意味着安全威胁。 (不确定是否存在任何其他问题)

  

你认为是最好的方法之一(或者我根本没想过的东西),在哪里可以找到一些代码示例?

提前致谢。

[编辑]

我找到了这个 - http://blog.pelicandd.com/article/80/streaming-input-and-output-in-flask,作者正处理类似我的类似情况,他提出了一个解决方案。但他正在打开磁盘中已存在的文件。如果我想直接上传文件作为s3存储桶中的单个对象,该怎么办?我觉得这可以作为解决方案的基础,但不是解决方案本身。

3 个答案:

答案 0 :(得分:3)

或者,您可以使用Minio-py客户端库,其开源并与S3 API兼容。它本身可以为您处理分段上传。

一个简单的 put_object.py 示例:

import os

from minio import Minio
from minio.error import ResponseError

client = Minio('s3.amazonaws.com',
               access_key='YOUR-ACCESSKEYID',
               secret_key='YOUR-SECRETACCESSKEY')

# Put a file with default content-type.
try:
    file_stat = os.stat('my-testfile')
    file_data = open('my-testfile', 'rb')
    client.put_object('my-bucketname', 'my-objectname', file_data, file_stat.st_size)
except ResponseError as err:
    print(err)

# Put a file with 'application/csv'
try:
    file_stat = os.stat('my-testfile.csv')
    file_data = open('my-testfile.csv', 'rb')
    client.put_object('my-bucketname', 'my-objectname', file_data,
                      file_stat.st_size, content_type='application/csv')
except ResponseError as err:
    print(err)

您可以使用示例here

找到完整API操作的列表

安装Minio-Py库

$ pip install minio

希望它有所帮助。

免责声明:我为Minio

工作

答案 1 :(得分:1)

  1. Flask只能使用内存来保存所有的http请求体,所以没有像我所知的那样的功能,比如磁盘缓冲。
  2. Nginx上传模块是一个非常好的大文件上传方式。该文件是here
  3. 您还可以使用html5,flash发送中继文件数据并在Flask中处理数据,但这很复杂。
  4. 尝试查看s3是否提供一次性令牌。

答案 2 :(得分:0)

使用我上面发布的链接,我终于完成了以下操作。如果您认为这是一个很好的解决方案,请告诉我

import boto3
from flask import Flask, request

.
.
.

@app.route('/upload', methods=['POST'])
def upload():
    s3 = boto3.resource('s3', aws_access_key_id="key", aws_secret_access_key='secret', region_name='us-east-1')
    s3.Object('bucket-name','filename').put(Body=request.stream.read(CHUNK_SIZE))
.
.
.