View index.js
function drawArray(arr) {
Thanks original author @vukicevic
Pass a two-dimensional arrary.
The first dimonsion is rows, the second one is columns.
Note that in columns, each pixel is represented by four nums as BGRA, so the columns' length is four times as image's length.
return image's base64 code.

asyncio won't automatically create event loop for sub-thread, so to run async tasks in sub-thread, we need to manually create an event loop first.

loop = asyncio.new_event_loop()

tornado has its own event loop which is incompatible with asyncio's event loop. But it can be solved.

First, create a BaseHandler extended from tornado.web.RequestHandler:

class BaseHandler(tornado.web.RequestHandler):

    def asyncio_task(method):
        async def wrapper(self, *args, **kwargs):

nginx-upload-module is really a good module which saves uploaded files to local temp directory with nginx itself and sends related information to backends.

But its official repository seems died many years ago, and that makes it incompatible with latest nginx. Fortunately, there is a forked repository [] can be used.

But if you are using Ubuntu 16.04, additionally, you need to manually change compile flags to avoid some errors such as undefined reference to 'MD5_Update':

After ./configure [configure flag], you need to vim ./objs/Makefile

and change