使用 SocketIO 上传文件时,Flask request.stream.read() 正在停止
Posted
技术标签:
【中文标题】使用 SocketIO 上传文件时,Flask request.stream.read() 正在停止【英文标题】:Flask request.stream.read() is stopping when uploading file using SocketIO 【发布时间】:2020-12-20 16:30:32 【问题描述】:我正在使用 flask-socketio 和 eventlet 运行 Flask 生产服务器,当尝试提交包含要上传的文件的表单时,Flask 无法读取整个请求。当文件超过几 kb(大约 50kb 或更多)时,就会发生这种情况。我要上传的文件是一个 60kb 的 .txt 文件,每行都有一个单词。文件大小为 1-2kb 的情况下,一切正常。
def get_file(request):
if 'uploadFile' not in request.files:
return redirect(request.url)
return = request.file['uploadFile']
经过一些测试,我能够确定代码没有通过检查request.files
。例如,我会尝试 print(request.files)
并且代码不会从那里继续前进,它只会挂起。
我知道 Flask 的内置方法可能不是最有效的,所以我找到了一个库 streaming-form-data
可以帮助加载大文件,因此将其实现为替代
def get_file(request):
parser = StreamingFormDataParser(headers=request.headers)
parser.register('file', FileTarget('/temp/file.txt')
while True:
chunk = request.stream.read(8192)
if not chunk:
break
parser.data_received(chunk) # add read bytes to file
socketio.sleep(1)
文件仍然无法完成上传,但是我发现它在尝试执行chunk = request.stream.read(8192)
时停止。这不会立即发生,它通常会在第 4-5 次迭代左右停止。在有和没有socketio.sleep()
的情况下进行了测试,据我所知,这对于需要更多时间的任务来说可能是必需的。
我使用 Flask Dev Server 进行了更多测试,发现如果我使用app.run(threaded=True)
,它将按预期完成并且代码将继续。但是我无法使用socketio.run()
和 eventlet 让它工作,例如我的main.py
import eventlet
eventlet.monkey_patch()
from app import app, socketio
if __name__ == "__main__":
# app.run(threaded=True) # This will work and finish loading the file
socketio.run(app) # does not work
在while
循环读取流期间我没有收到任何错误,只是没有继续获取下一个chunk = request.stream.read(8192)
【问题讨论】:
【参考方案1】:找到了我需要的解决方案,结果发现它真的不是 Flask 的问题。在我的 POST 中,我只需要包含 chunking: true
,它似乎从那里工作正常。
例如
$.ajax(
type: 'POST',
chunking: true,
data: form_data,
contentType: false,
);
作为测试,我恢复了我在上面所做的更改(尽管这些更改可能是为了更好)并确认它有效。
【讨论】:
以上是关于使用 SocketIO 上传文件时,Flask request.stream.read() 正在停止的主要内容,如果未能解决你的问题,请参考以下文章
使用 pytest 测试 flask-socketio 服务器发出的事件时出错
尽管使用了 socketio.run(),但“Flask-SocketIO 正在 Werkzeug 下运行”
如何等待传递给 Flask-SocketIO 的 emit() 的回调?