Uploading multiple files to the tornado webserver
The following html code can be used to create an html form that allows uploading multiple files at once:
<form enctype="multipart/form-data" method="POST" action="upload.py">
<table style="width: 100%">
<tr>
<td>Choose the files to upload:</td>
<td style="text-align: right"><input type="file" multiple="" id="files" name="files"></td>
</tr>
<tr>
<td><input id="fileUploadButton" type="submit" value="Upload >>"></td>
<td></td>
</tr>
</table>
</form>
Using the tornado webserver it is then possible to handle the incoming requests containing an unknown number of files with something like this:
class UploadFile(tornado.web.RequestHandler):
# handle a post request
def post(self):
# ... maybe add a check that checks whether the user is allowed to upload anything ...
# the file(s) that should get uploaded
files = []
# check whether the request contains files that should get uploaded
try:
files = self.request.files['files']
except:
pass
# for each file that should get uploaded
for xfile in files:
# get the default file name
file = xfile['filename']
# the filename should not contain any "evil" special characters
# basically "evil" characters are all characters that allows you to break out from the upload directory
index = file.rfind(".")
filename = file[:index].replace(".", "") + str(time.time()).replace(".", "") + file[index:]
filename = filename.replace("/", "")
# save the file in the upload folder
with open("uploads/%s" % (filename), "w") as out:
# Be aware, that the user may have uploaded something evil like an executable script ...
# so it is a good idea to check the file content (xfile['body']) before saving the file
out.write(xfile['body'])
Keep in mind, that the tornado webserver is storing the complete html request in RAM - which may be to much for a webserver, if multiple users are simultanously uploading big files. So you may need to limit the maximal upload size. If you are using the nginx webserver in combination with tornado, you can limit the maximal upload size in the nginx config file:
# ...
http {
# ...
client_max_body_size 100m; # a value of 0 disables max_body_size checking ...
# ...
}