17

I saw examples that used pycurl, but could not be sure if this is the way to go with? Some examples will help. Thanks.

5 Answers 5

23

Here is demo application that implements tornado upload.

Here is server code:

import tornado.httpserver, tornado.ioloop, tornado.options, tornado.web, os.path, random, string
from tornado.options import define, options

define("port", default=8888, help="run on the given port", type=int)

class Application(tornado.web.Application):
    def __init__(self):
        handlers = [
            (r"/", IndexHandler),
            (r"/upload", UploadHandler)
        ]
        tornado.web.Application.__init__(self, handlers)

class IndexHandler(tornado.web.RequestHandler):
    def get(self):
        self.render("upload_form.html")

class UploadHandler(tornado.web.RequestHandler):
    def post(self):
        file1 = self.request.files['file1'][0]
        original_fname = file1['filename']
        extension = os.path.splitext(original_fname)[1]
        fname = ''.join(random.choice(string.ascii_lowercase + string.digits) for x in range(6))
        final_filename= fname+extension
        output_file = open("uploads/" + final_filename, 'w')
        output_file.write(file1['body'])
        self.finish("file" + final_filename + " is uploaded")

def main():
    http_server = tornado.httpserver.HTTPServer(Application())
    http_server.listen(options.port)
    tornado.ioloop.IOLoop.instance().start()

if __name__ == "__main__":
    main()

The only thing, you have to understand from this code, that file content located in self.request.files[<file_input_name>][0].

Here is html code:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> 
<html xmlns="http://www.w3.org/1999/xhtml"> 
<head> 
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> 
<title>Tornado Upload Application</title>
</head>
<body>
<p><h1>Tornado Upload App</h1></p>
<form enctype="multipart/form-data" action="/upload" method="post">
File: <input type="file" name="file1" />
<br />
<br />
<input type="submit" value="upload" />
</form>

When working with files - be sure, that form has enctype="multipart/form-data".

Sign up to request clarification or add additional context in comments.

1 Comment

One small remark: in python3.x you need to open the file in write binary mode. So it will be: output_file = open("uploads/" + final_filename, 'wb') This is due to the different handling of strings(unicode) and byte strings in python3. more here
17

It's simple:

<form action="/file" methods="POST"><!--your code--></form>

in Python:

class FileHandler(tornado.web.RequestHandler):
    # get post data
    file_body = self.request.files['filefieldname'][0]['body']
    img = Image.open(io.StringIO(file_body))
    img.save("../img/", img.format)

but it's not recommended, because all uploaded data is loaded in RAM; the best way is use nginx loadup module, but this is complex.

2 Comments

why is dir() necessary here? I want to upload the file in /../img/ directory
@AniruddhaJana is not necessary, only output data to console.
6

Previous code returned bad filename and wrong encoding. Following code works:

import tornado.httpserver, tornado.ioloop, tornado.options, tornado.web, os.path, random, string




class Application(tornado.web.Application):
    def __init__(self):
        handlers = [
            (r"/", IndexHandler),
            (r"/upload", UploadHandler)
        ]
        tornado.web.Application.__init__(self, handlers)

class IndexHandler(tornado.web.RequestHandler):
    def get(self):
        self.render("tornadoUpload.html")

class UploadHandler(tornado.web.RequestHandler):
    def post(self):
        file1 = self.request.files['file1'][0]
        original_fname = file1['filename']

        output_file = open("uploads/" + original_fname, 'wb')
        output_file.write(file1['body'])

        self.finish("file " + original_fname + " is uploaded")

settings = {
'template_path': 'templates',
'static_path': 'static',
"xsrf_cookies": False

}
application = tornado.web.Application([
   (r"/", IndexHandler),
            (r"/upload", UploadHandler)


], debug=True,**settings)



print "Server started."
if __name__ == "__main__":
    application.listen(8888)
    tornado.ioloop.IOLoop.instance().start()

Comments

4

I was running into trouble when accesses the files properties with the [''] syntax, not sure why, but I switched to dot syntax and was able to read the data. I'm on a windows machine so I also had to change 'open("static/public/" + file_name, 'w')' to 'open("static/public/" + file_name, 'wb')'. Without the 'wb' the files were getting corrupted.

def uploadFile(self,input_name,file_type):
            a_file = self.request.files[input_name][0]
            extension = os.path.splitext(a_file.filename)[1]

            if file_type is 'photo':
                type_list = ['.png','.jpg','.jpeg','.gif']
            elif file_type is 'attachment':
                type_list = ['.pdf','.doc','.docx','.xls']

            if extension in type_list:
                file_name = ''.join(random.choice(string.ascii_lowercase + string.digits) for x in range(16))
                output_file = open("static/public/" + file_name + extension, 'wb')
                output_file.write(a_file.body)
                return (a_file.filename + " has been uploaded.")

Comments

0

tornado.web.RequestHandler has self.request.files method. it's result like

{u'file': [{'body':FILEBODY, 'content_type':CONTENT_TYPE, 'filename': FILENAME}],...}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.