I'm creating an application using tornado 6.0.3 and need to upload large files using an html form. How do I stream the files, eg using the @stream_request_body
decorator, to do this?
I have created a simple form which looks like this:
<form action="{{ reverse_url('upload') }}" method="post" enctype="multipart/form-data">
{% module xsrf_form_html() %}
<input class="file" name="filesToUpload" id="filesToUpload" type="file" multiple/>
<input type="submit" name="submit" value="Upload File(s)"/>
</form>
which redirects to the tornado handler UploadHandler and uploads (to current working directory) the chosen files:
class UploadHandler(BaseHandler):
"""Class. Handles the upload of the file."""
def post(self):
files = []
try:
files = self.request.files['filesToUpload']
except:
pass
for f in files:
file = f['filename']
with open(file, "wb") as out:
out.write(f['body'])
This works, but I need to be able to handle huge files so I can't load the files in memory. Therefore I tried to use the @stream_request_body
decorator and I found (among others) this solution, but as soon as I add the @stream_request_body
I get the following error:
Traceback (most recent call last): File "/usr/local/lib/python3.6/dist-packages/tornado/web.py", line 1674, in _execute self.check_xsrf_cookie() File "/usr/local/lib/python3.6/dist-packages/tornado/web.py", line 1516, in check_xsrf_cookie raise HTTPError(403, "'_xsrf' argument missing from POST") tornado.web.HTTPError: HTTP 403: Forbidden ('_xsrf' argument missing from POST)
I then found this where it says that my tornado version doesn't support streaming multiple-parts uploads, so I (since I'm using tornado version 6.0.3) need to change my form method from POST to PUT and pass the XSRF token via an HTTP header. However, html forms don't support the PUT method, so I'm guessing I need to use JavaScript for this in some way, but I've not used JavaScript much and I haven't found any help on how to do this.
So my questions are:
- How do I stream my files from the form using the latest version of tornado, using PUT and (or anything else that will work) JavaScript?
- How to I pass the XSRF token via an HTTP header? I haven't found any actual code example on how to do this.
Thank you in advance!