Tornado Application
download#!/usr/bin/env python
# coding:utf-8
import os
import uuid
from fs import open_fs
from tornado.web import Application, RequestHandler, url, StaticFileHandler
from tornado.httpserver import HTTPServer
from tornado.ioloop import IOLoop
fs = open_fs('osfs://uploads/')
class Userform(RequestHandler):
<span class="k">def</span> <span class="nf">get</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">render</span><span class="p">(</span><span class="s2">"upload.html"</span><span class="p">)</span>
# noinspection PyAbstractClass
class AsyncFileUploadHandler(RequestHandler):
"""
Uploader
"""
<span class="k">def</span> <span class="nf">upload_async</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">filepart</span><span class="p">):</span>
<span class="n">filename</span> <span class="o">=</span> <span class="n">filepart</span><span class="p">[</span><span class="s1">'filename'</span><span class="p">]</span>
<span class="n">extension</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">splitext</span><span class="p">(</span><span class="n">filename</span><span class="p">)[</span><span class="mi">1</span><span class="p">]</span>
<span class="n">unique_name</span> <span class="o">=</span> <span class="nb">str</span><span class="p">(</span><span class="n">uuid</span><span class="o">.</span><span class="n">uuid4</span><span class="p">())</span> <span class="o">+</span> <span class="n">extension</span>
<span class="n">fs</span><span class="o">.</span><span class="n">setbytes</span><span class="p">(</span><span class="n">unique_name</span><span class="p">,</span> <span class="n">filepart</span><span class="p">[</span><span class="s1">'body'</span><span class="p">])</span>
<span class="k">return</span> <span class="n">unique_name</span>
<span class="k">def</span> <span class="nf">post</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="n">files</span> <span class="o">=</span> <span class="nb">tuple</span><span class="p">(</span><span class="nb">map</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">upload_async</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">request</span><span class="o">.</span><span class="n">files</span><span class="p">[</span><span class="s1">'file'</span><span class="p">]))</span>
<span class="n">urls</span> <span class="o">=</span> <span class="nb">tuple</span><span class="p">(</span><span class="nb">map</span><span class="p">(</span><span class="k">lambda</span> <span class="n">name</span><span class="p">:</span> <span class="sa">f</span><span class="s1">'/uploads/</span><span class="si">{</span><span class="n">name</span><span class="si">}</span><span class="s1">'</span><span class="p">,</span> <span class="n">files</span><span class="p">))</span>
<span class="n">data</span> <span class="o">=</span> <span class="nb">dict</span><span class="p">(</span><span class="n">files</span><span class="o">=</span><span class="n">files</span><span class="p">,</span> <span class="n">urls</span><span class="o">=</span><span class="n">urls</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">finish</span><span class="p">(</span><span class="n">data</span><span class="p">)</span>
handlers = [
(r"/", Userform),
url(pattern=r'/upload', handler=AsyncFileUploadHandler, name='upload'),
(r"/uploads/(.*)", StaticFileHandler, {"path": "uploads"})
]
App = Application(handlers=handlers, **dict(debug=False,
autoreload=False, logging='debug'))
if name == "main":
server = HTTPServer(App)
server.bind(port=8000)
server.start(num_processes=1)
IOLoop.current().start()
Docker Compose
downloadversion: "3"
services:
app:
build: .
volumes:
- ./uploads:/uploads
ports:
- "8000:8000"
Dockerfile
downloadFROM guneysu/python:3-onbuild
VOLUME ["/uploads"]
ADD app /app
WORKDIR /
CMD python -m app
Makefile
downloaddefault: run
build:
@docker-compose build
run: build
@docker-compose up
test:
@http -f POST :8000/upload [email protected] [email protected]
down:
@docker-compose down
develop:
@docker-compose up –build
.PHONY: default build run test down develop
Running
docker-compose up -d
Testing
http -f POST :8000/ [email protected]
HTTP/1.1 200 OK
Content-Length: 215
Content-Type: application/json; charset=UTF-8
Date: Sat, 02 May 2020 14:36:36 GMT
Server: TornadoServer/4.5.1
{
"files": [
"6936cd27-01dc-4af6-adf9-970ad168ed6b.txt",
"1c7052d7-0e29-4eb4-a914-f58d78289add.txt"
],
"urls": [
"/uploads/6936cd27-01dc-4af6-adf9-970ad168ed6b.txt",
"/uploads/1c7052d7-0e29-4eb4-a914-f58d78289add.txt"
]
}