Skip to content

Instantly share code, notes, and snippets.

@alex8224
Last active May 5, 2019 06:48
Show Gist options
  • Save alex8224/e1c438f0d2034daeb44c to your computer and use it in GitHub Desktop.
Save alex8224/e1c438f0d2034daeb44c to your computer and use it in GitHub Desktop.
A multipart form parse for tornado
#!/usr/bin/env python
#-*-coding:utf-8 -*-
#
#Author: alex alex8224 at gmail.com
#Create by:2015-08-11 15:50:21
#Last modified:2015-10-10 09:19:05
#Filename:server.py
#Description:
from __future__ import absolute_import
import re
import sys
from cStringIO import StringIO
import tornado.ioloop
import tornado.options
import tornado.httpserver
from tornado.log import app_log
from tornado.web import RequestHandler, Application, stream_request_body
@tornado.web.stream_request_body
class UploadHandler(BaseHandler):
def prepare(self):
self.mimetype = self.request.headers.get("Content-Type")
self.boundary = "--%s" % (self.mimetype[self.mimetype.find("boundary")+9:])
self.state = constant.PARSE_READY
self.output = None
self.find_filename = re.compile('filename="(.*)"')
self.find_mimetype = re.compile('Content-Type: (.*)')
self.find_field = re.compile('name="(.*)"')
def post(self):
self.write("upload ok")
def data_received(self, data):
buff = data.split(self.boundary)
for index, part in enumerate(buff):
if part:
if part == "--\r\n":
break
if self.state == constant.PARSE_FILE_PENDING:
if len(buff) > 1:
self.output.write(part[:-2])
self.output.close()
self.state = constant.PARSE_READY
continue
else:
self.output.write(part)
continue
elif self.state == constant.PARSE_READY:
stream = StringIO(part)
stream.readline()
form_data_type_line = stream.readline()
if form_data_type_line.find("filename") > -1:
filename = re.search(self.find_filename, form_data_type_line).groups()[0]
self.output = open("/tmp/%s" % filename.encode("utf-8"), "wb")
content_type_line = stream.readline()
mimetype = re.search(self.find_mimetype, content_type_line).groups()[0]
app_log.debug("%s with %s" % (filename, mimetype.strip()))
stream.readline()
body = stream.read()
if len(buff) > index + 1:
self.output.write(body[:-2])
self.state = constant.PARSE_READY
else:
self.output.write(body)
self.state = constant.PARSE_FILE_PENDING
else:
stream.readline()
form_name = re.search(self.find_field, form_data_type_line).groups()[0]
form_value = stream.readline()
self.state = constant.PARSE_READY
app_log.debug("%s=%s" % (form_name.strip(), form_value.strip()))
if __name__ == '__main__':
settings = {"debug":True, "autoreload":True}
app = Application([(r"/", UploadHandler)], **settings)
http_server = tornado.httpserver.HTTPServer(app, xheaders=True)
http_server.listen(30001)
print("server listen")
tornado.ioloop.IOLoop.instance().start()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment