使用 SocketIO 上传文件时 Flask request.stream.read() 停止
Flask request.stream.read() is stopping when uploading file using SocketIO
我是 运行 使用 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)
找到了我需要的解决方案,结果证明这真的不是 Flask 的问题。在我的 POST 中,我只需要包含 chunking: true
并且从那里开始似乎工作正常。
例如
$.ajax({
type: 'POST',
chunking: true,
data: form_data,
contentType: false,
});
作为测试,我恢复了上面所做的更改(尽管这些更改可能会变得更好)并确认它有效。
我是 运行 使用 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)
找到了我需要的解决方案,结果证明这真的不是 Flask 的问题。在我的 POST 中,我只需要包含 chunking: true
并且从那里开始似乎工作正常。
例如
$.ajax({
type: 'POST',
chunking: true,
data: form_data,
contentType: false,
});
作为测试,我恢复了上面所做的更改(尽管这些更改可能会变得更好)并确认它有效。