2016-12-01 120 views
0

我正在處理大型文件上傳(250 MB +)的Flask應用程序。我正在使用Tornado運行這個應用程序,並使用多個進程,因此它可以處理併發請求而不會阻塞。將大文件上傳到Tornado HTTP服務器時出現MemoryError

import os.path 
import tempfile 
from flask import Flask, request, jsonify 
from tornado.wsgi import WSGIContainer 
from tornado.httpserver import HTTPServer 
from tornado.ioloop import IOLoop 
from werkzeug import secure_filename 

app = Flask(__name__) 

@app.route("/test", methods=["GET"]) 
def test_route(): 

    return jsonify(msg='Ok'), 200 

@app.route("/upload", methods=["GET", "POST"]) 
def upload_file(): 

    if request.method == 'POST': 
     temp_directory = app.config['TMP_DIRECTORY'] 
     uploaded_file = request.files['filename'] 
     filename = secure_filename(uploaded_file.filename) 
     uploaded_file.save(os.path.join(temp_directory, filename)) 
     return jsonify(msg="File upload successfully"), 200 

    else: 
     return jsonify(msg="Use POST to upload a file"), 200 


if __name__ == '__main__': 
    app.config['TMP_DIRECTORY'] = tempfile.mkdtemp() 
    address = '0.0.0.0' 
    port = 8000 

    max_buffer_size = 500 * 1024 * 1024 
    server = HTTPServer(WSGIContainer(app), max_buffer_size=max_buffer_size) 
    server.bind(port=port, address=address) 

    print("Starting Tornado server on %s:%s" % (address, port)) 
    server.start(2) 
    IOLoop.instance().start() 

同時上傳多個大文件時,我得到了以下的MemoryError:

$ curl -i -F name=file -F [email protected] http://127.0.0.1:8000/upload 

ERROR:tornado.application:Uncaught exception 
Traceback (most recent call last): 
    File "/usr/lib64/python2.7/site-packages/tornado/http1connection.py", line 238, in _read_message 
    delegate.finish() 
    File "/usr/lib64/python2.7/site-packages/tornado/httpserver.py", line 285, in finish 
    self.request.body = b''.join(self._chunks) 
MemoryError 

相信龍捲風在內存中存儲整個上傳的文件,一旦客戶只需將其寫入到磁盤完成上傳。是否有可能修改此行爲將塊寫入磁盤?

回答

1

您誤解了Tornado的工作原理。它並不神奇地讓你的Flask應用「能夠處理併發請求而不會阻塞」 - 在Tornado的WSGIContainer中使用Flask是較少可伸縮比在諸如uwsgigunicorn的東西上使用Flask更靈活。請參閱warning in WSGIContainer's documentation

如果你是以原生Tornado應用程序(沒有Flask)的方式來做這件事,那麼你可以使用tornado.web.stream_request_body修飾器來處理大的上傳而不緩衝整個內存。

+0

你是完全正確的。我將使用gunicorn。 –

相關問題