Skip to content

Instantly share code, notes, and snippets.

@Ivlyth
Last active February 18, 2016 03:53
Show Gist options
  • Save Ivlyth/251fbbbf6d5b509c6ca4 to your computer and use it in GitHub Desktop.
Save Ivlyth/251fbbbf6d5b509c6ca4 to your computer and use it in GitHub Desktop.
用tornado+nginx + supervisord 搭建一个简单的文件上传下载, 方便在多服务器间以及与本地间文件拷贝

##上传文件

Web

使用浏览器访问 YOUR.DOMAIN.COM/up , 然后选择文件, 点击上传

Curl

使用命令 curl YOUR.DOMAIN.COM -T *FILE*


##下载文件

Web

使用浏览器访问 YOUR.DOMAIN.COM/FILE

Curl

使用命令 curl -o *NAME* YOUR.DOMAIN.COM/*FILE*

Wget

使用命令 wget YOUR.DOMAIN.COM/*FILE*

# 将以下内容贴到你的nginx配置文件的 http 段中
upstream updown {
server 127.0.0.1:8881;
server 127.0.0.1:8882;
server 127.0.0.1:8883;
server 127.0.0.1:8884;
}
server {
listen 80;
server_name YOUR.DOMAIN.COM;
#注意一定要修改client_max_body_size, 不然上传大文件nginx会返回413 Request Entity Too Large Error
client_max_body_size 2048M;
location / {
proxy_pass http://updown;
}
}
# supervisord 配置
[program:updown-8881]
command=python /data1000g/myth/updown_server.py --port=8881
autostart=true
redirect_stderr=true
[program:updown-8882]
command=python /data1000g/myth/updown_server.py --port=8882
autostart=true
redirect_stderr=true
[program:updown-8883]
command=python /data1000g/myth/updown_server.py --port=8883
autostart=true
redirect_stderr=true
[program:updown-8884]
command=python /data1000g/myth/updown_server.py --port=8884
autostart=true
redirect_stderr=true
#!/usr/bin/env python
# -*- coding:utf8 -*-
'''
Author : Myth
Date : 15/1/28
Email : belongmyth at 163.com
'''
import sys
reload(sys)
sys.setdefaultencoding(u'utf-8')
import os
import uuid
import tornado
from tornado.web import RequestHandler
import tornado.ioloop
import tornado.httpserver
from tornado.options import options, define, parse_command_line
from tornado.web import StaticFileHandler
from tornado import gen
SCRIPT_NAME = os.path.split(__file__)[-1]
# the directory which contains this script will be the
# directory contains the upload files
ROOT_PATH = os.path.dirname(os.path.abspath(__file__))
define(u'port', default=8989, type=int, help=u'Tornado will provide service on the given port')
@tornado.web.stream_request_body
class CurlStreamUploadHandler(StaticFileHandler):
# using tmp file to store the upload data
# then rename it
def prepare(self):
self.tmp_file_name = os.path.join(ROOT_PATH, str(uuid.uuid4()))
# stream upload
def data_received(self, chunk):
if chunk:
open(self.tmp_file_name, u'ab').write(chunk)
def list_dir(self, directory):
protocol = self.request.protocol
host = self.request.host
fs = os.listdir(directory)
html = []
for f in sorted(fs):
if f == u'myth' and os.path.isdir(os.path.join(directory, f)):
continue
if f == SCRIPT_NAME:
continue
html.append(u'<a href="%(protocol)s://%(host)s/%(path)s%(file)s">%(file)s</a>' % {
u'protocol': protocol,
u'path': (self.request.path.strip(u'/') + u'/') if self.request.path.strip(u'/') else u'',
u'host': host,
u'file': f
})
html.append(u'''
<div id="clustrmaps-widget"></div><script type="text/javascript">var _clustrmaps = {'url' : 'http://w.myth.ren', 'user' : 1177302, 'server' : '3', 'id' : 'clustrmaps-widget', 'version' : 1, 'date' : '2015-08-27', 'lang' : 'zh', 'corners' : 'square' };(function (){ var s = document.createElement('script'); s.type = 'text/javascript'; s.async = true; s.src = 'http://www3.clustrmaps.com/counter/map.js'; var x = document.getElementsByTagName('script')[0]; x.parentNode.insertBefore(s, x);})();</script><noscript><a href="http://www3.clustrmaps.com/user/e3111f6d6"><img src="http://www3.clustrmaps.com/stats/maps-no_clusters/w.myth.ren-thumb.jpg" alt="Locations of visitors to this page" /></a></noscript>
''')
self.write(u'<br/>'.join(html))
@gen.coroutine
def get(self, path, include_body=True):
self.set_header(u'Cache-Control', u'no-store')
# access roor directory
if path is None:
self.list_dir(ROOT_PATH)
self.absolute_path = ROOT_PATH
return
absolute_path = self.get_absolute_path(self.root, self.parse_url_path(path))
# access some directory
if os.path.isdir(absolute_path):
self.list_dir(absolute_path)
self.absolute_path = absolute_path
return
yield super(CurlStreamUploadHandler, self).get(path, include_body)
def put(self, path):
# when using curl -T to upload file
# you can specify the directory through
# `Upload-To` header where
# will store the file you upload
upload_to = self.request.headers.get(u'Upload-To', None)
if upload_to:
d, filename = os.path.split(os.path.join(ROOT_PATH, path))
parent_dir = os.path.join(ROOT_PATH, upload_to)
else:
parent_dir, filename = os.path.split(os.path.join(ROOT_PATH, path))
try:
os.makedirs(parent_dir)
except:
pass
if os.path.exists(self.tmp_file_name):
real_name = os.path.join(parent_dir, filename)
os.system(u"mv %s '%s' -f" % (self.tmp_file_name, real_name))
self.write(u'upload success\n')
def delete(self, path):
real_name = os.path.join(ROOT_PATH, path)
if not os.path.exists(real_name):
self.set_status(404)
self.write(u'%s not found\n' % path)
return
if os.path.isdir(real_name):
self.set_status(403)
self.write(u'%s is a directory\n' % path)
return
os.system(u'rm -f %s' % real_name)
self.write(u'delete %s success\n' % path)
class UploadHandler(RequestHandler):
def get(self):
html = u'''
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<title>Upload Form</title>
</head>
<body>
<p><h1>上传文件</h1></p>
<form enctype="multipart/form-data" action="/up" method="post">
选择文件: <input type="file" name="upfile" multiple/><br/>
上传至目录: <input type="text" name="upload_to" />
<br />
<br />
<input type="submit" value="点击上传" />
</form>
'''
self.write(html)
# for web
def post(self):
upload_to = self.get_body_argument(u'upload_to', u'')
if not self.request.files:
self.write(u'请选择文件!!!')
return
if u'upfile' not in self.request.files:
self.write(u'What ?')
return
if not self.request.files[u'upfile']:
self.write(u'请选择文件!!!')
return
for f in self.request.files[u'upfile']:
name = f.get(u'filename', None)
if name is None:
self.write(u'文件名呢?')
return
upload_dir = os.path.join(ROOT_PATH, upload_to)
try:
os.makedirs(upload_dir)
except:
pass
print os.path.join(upload_dir, name)
open(os.path.join(upload_dir, name), u'wb').write(f.get(u'body', u''))
self.write(u'upload success %d files' % len(self.request.files[u'upfile']))
url_patterns = [
# upload files through browsers
(ur'/up', UploadHandler),
# upload file through `curl -T`(stream upload)/download file/list directory
(ur'/(?P<path>.+)?', CurlStreamUploadHandler, {u'path': ROOT_PATH})
]
def main():
application = tornado.web.Application(url_patterns)
# modify the max_buffer_size to allow user to upload large files
application.listen(options.port, max_buffer_size=1024 * 1024 * 1024 * 1024)
tornado.ioloop.IOLoop.current().start()
if __name__ == u'__main__':
parse_command_line()
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment