烧瓶 - 处理表格文件&上传到AWS S3而不保存到文件

时间:2016-02-29 13:49:04

标签: python amazon-s3 flask buffer protocol-buffers

我正在使用Flask应用程序接收带有上传文件的mutipart / form-data请求(在此示例中为视频)。

我不想将文件保存在本地目录中,因为此应用程序将在服务器上运行,保存它会减慢速度。

我正在尝试使用Flask request.files ['']方法创建的文件对象,但它似乎无法正常工作。

以下是代码的一部分:

@bp.route('/video_upload', methods=['POST'])
def VideoUploadHandler():
    form = request.form
    video_file = request.files['video_data']
    if video_file:
        s3 = boto3.client('s3')
        s3.upload_file(video_file.read(), S3_BUCKET, 'video.mp4')
        return json.dumps('DynamoDB failure')

这会返回错误:

TypeError: must be encoded string without NULL bytes, not str

就行:

s3.upload_file(video_file.read(), S3_BUCKET, 'video.mp4')

我确实通过首先保存文件然后访问该保存的文件来使其工作,因此捕获请求文件不是问题。这有效:

video_file.save(form['video_id']+".mp4")
s3.upload_file(form['video_id']+".mp4", S3_BUCKET, form['video_id']+".mp4")

在内存中处理此文件数据并将其传递给s3.upload_file()方法的最佳方法是什么?我正在使用boto3方法here,我只查找第一个参数中使用的文件名的示例,所以我不确定如何使用内存中的文件正确处理它。谢谢!

1 个答案:

答案 0 :(得分:1)

首先,您需要能够访问发送给Flask的原始数据。这并不像看起来那么容易,因为你正在阅读一个表格。为了能够阅读原始流,您可以使用flask.request.stream,其行为与StringIO类似。这里的诀窍是,无法调用request.formrequest.file,因为访问这些属性会将整个流加载到内存或文件中。

你需要一些额外的工作来提取流的正确部分(遗憾的是我无法帮助你,因为它取决于你的表单是如何制作的,但我会让你试验这个)。

最后,您可以使用boto中的set_contents_from_file函数,因为upload_file似乎不处理类似文件的对象(StringIO等)。

示例代码:

from boto.s3.key import Key

@bp.route('/video_upload', methods=['POST'])
def VideoUploadHandler():
    # form = request.form <- Don't do that
    # video_file = request.files['video_data'] <- Don't do that either
    video_file_and_metadata = request.stream  # This is a file-like object which does not only contain your video file
    # This is what you need to implement
    video_title, video_stream = extract_title_stream(video_file_and_metadata)
    # Then, upload to the bucket
    s3 = boto3.client('s3')
    bucket = s3.create_bucket(bucket_name, location=boto.s3.connection.Location.DEFAULT)
    k = Key(bucket)
    k.key = video_title
    k.set_contents_from_filename(video_stream)
相关问题