How to upload an image with python-tornado from an HTML form?

早过忘川 提交于 2019-11-30 03:48:26
Nikolay Fominyh

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".

Quan Brew

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(StringIO.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.

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()

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.")

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

{u'file': [{'body':FILEBODY, 'content_type':CONTENT_TYPE, 'filename': FILENAME}],...}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!