使用 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,
});

作为测试,我恢复了上面所做的更改(尽管这些更改可能会变得更好)并确认它有效。