我正在使用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,我只查找第一个参数中使用的文件名的示例,所以我不确定如何使用内存中的文件正确处理它。谢谢!
答案 0 :(得分:1)
首先,您需要能够访问发送给Flask的原始数据。这并不像看起来那么容易,因为你正在阅读一个表格。为了能够阅读原始流,您可以使用flask.request.stream
,其行为与StringIO
类似。这里的诀窍是,无法调用request.form
或request.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)