simple HTTP server with upload
#!/usr/bin/env python """Simple HTTP Server With Upload. https://github.com/tualatrix/tools/blob/master/SimpleHTTPServerWithUpload.py This module builds on BaseHTTPServer by implementing the standard GET
and HEAD requests in a fairly straightforward manner. """ import os
import posixpath
import BaseHTTPServer
import urllib
import cgi
import shutil
import mimetypes
import re __version__ = "0.1"
__all__ = ["SimpleHTTPRequestHandler"]
__author__ = "bones7456"
__home_page__ = "http://li2z.cn/" try:
from cStringIO import StringIO
except ImportError:
from StringIO import StringIO class SimpleHTTPRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler): """Simple HTTP request handler with GET/HEAD/POST commands. This serves files from the current directory and any of its
subdirectories. The MIME type for files is determined by
calling the .guess_type() method. And can reveive file uploaded
by client. The GET/HEAD/POST requests are identical except that the HEAD
request omits the actual contents of the file. """ server_version = "SimpleHTTPWithUpload/" + __version__ def do_GET(self):
"""Serve a GET request."""
f = self.send_head()
if f:
self.copyfile(f, self.wfile)
f.close() def do_HEAD(self):
"""Serve a HEAD request."""
f = self.send_head()
if f:
f.close() def do_POST(self):
"""Serve a POST request."""
r, info = self.deal_post_data()
print r, info, "by: ", self.client_address
f = StringIO()
f.write('<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">')
f.write("<html>\n<meta charset='UTF-8'>\n<title>Upload Result Page</title>\n")
f.write("<html>\n<title>Upload Result Page</title>\n")
f.write("<body>\n<h2>Upload Result Page</h2>\n")
f.write("<hr>\n")
if r:
f.write("<strong>Success:</strong>")
else:
f.write("<strong>Failed:</strong>")
f.write(info)
f.write("<br><a href=\"%s\">back</a>" % self.headers['referer'])
f.write("<hr><small>Powered By: bones7456, check new version at ")
f.write("<a href=\"http://li2z.cn/?s=SimpleHTTPServerWithUpload\">")
f.write("here</a>.</small></body>\n</html>\n")
length = f.tell()
f.seek(0)
self.send_response(200)
self.send_header("Content-type", "text/html")
self.send_header("Content-Length", str(length))
self.end_headers()
if f:
self.copyfile(f, self.wfile)
f.close() def deal_post_data(self):
boundary = self.headers.plisttext.split("=")[1]
remainbytes = int(self.headers['content-length'])
line = self.rfile.readline()
remainbytes -= len(line)
if boundary not in line:
return (False, "Content NOT begin with boundary")
line = self.rfile.readline()
remainbytes -= len(line)
fn = re.findall(r'Content-Disposition.*name="file"; filename="(.*)"', line)
if not fn:
return (False, "Can't find out file name...")
path = self.translate_path(self.path)
fn = os.path.join(path, fn[0])
while os.path.exists(fn):
fn += "_"
line = self.rfile.readline()
remainbytes -= len(line)
line = self.rfile.readline()
remainbytes -= len(line)
try:
out = open(fn, 'wb')
except IOError:
return (False, "Can't create file to write, do you have permission to write?") preline = self.rfile.readline()
remainbytes -= len(preline)
while remainbytes > 0:
line = self.rfile.readline()
remainbytes -= len(line)
if boundary in line:
preline = preline[0:-1]
if preline.endswith('\r'):
preline = preline[0:-1]
out.write(preline)
out.close()
return (True, "File '%s' upload success!" % fn)
else:
out.write(preline)
preline = line
return (False, "Unexpect Ends of data.") def send_head(self):
"""Common code for GET and HEAD commands. This sends the response code and MIME headers. Return value is either a file object (which has to be copied
to the outputfile by the caller unless the command was HEAD,
and must be closed by the caller under all circumstances), or
None, in which case the caller has nothing further to do. """
path = self.translate_path(self.path)
f = None
if os.path.isdir(path):
if not self.path.endswith('/'):
# redirect browser - doing basically what apache does
self.send_response(301)
self.send_header("Location", self.path + "/")
self.end_headers()
return None
for index in "index.html", "index.htm":
index = os.path.join(path, index)
if os.path.exists(index):
path = index
break
else:
return self.list_directory(path)
ctype = self.guess_type(path)
try:
# Always read in binary mode. Opening files in text mode may cause
# newline translations, making the actual size of the content
# transmitted *less* than the content-length!
f = open(path, 'rb')
except IOError:
self.send_error(404, "File not found")
return None
self.send_response(200)
self.send_header("Content-type", ctype)
fs = os.fstat(f.fileno())
self.send_header("Content-Length", str(fs[6]))
self.send_header("Last-Modified", self.date_time_string(fs.st_mtime))
self.end_headers()
return f def list_directory(self, path):
"""Helper to produce a directory listing (absent index.html). Return value is either a file object, or None (indicating an
error). In either case, the headers are sent, making the
interface the same as for send_head(). """
try:
list = os.listdir(path)
except os.error:
self.send_error(404, "No permission to list directory")
return None
list.sort(key=lambda a: a.lower())
f = StringIO()
displaypath = cgi.escape(urllib.unquote(self.path))
f.write('<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">')
f.write("<html><meta charset='UTF-8'>\n<title>Directory listing for %s</title>\n" % displaypath)
f.write("<body>\n<h2>Directory listing for %s</h2>\n" % displaypath)
f.write("<hr>\n")
f.write("<form ENCTYPE=\"multipart/form-data\" method=\"post\">")
f.write("<input name=\"file\" type=\"file\"/>")
f.write("<input type=\"submit\" value=\"upload\"/></form>\n")
f.write("<hr>\n<ul>\n")
for name in list:
if '.py' not in name and '.html' not in name:
fullname = os.path.join(path, name)
displayname = linkname = name
# Append / for directories or @ for symbolic links
if os.path.isdir(fullname):
displayname = name + "/"
linkname = name + "/"
if os.path.islink(fullname):
displayname = name + "@"
# Note: a link to a directory displays with @ and links with /
f.write('<li><a href="%s">%s</a>\n'
% (urllib.quote(linkname), cgi.escape(displayname)))
f.write("</ul>\n<hr>\n</body>\n</html>\n")
length = f.tell()
f.seek(0)
self.send_response(200)
self.send_header("Content-type", "text/html")
self.send_header("Content-Length", str(length))
self.end_headers()
return f def translate_path(self, path):
"""Translate a /-separated PATH to the local filename syntax. Components that mean special things to the local file system
(e.g. drive or directory names) are ignored. (XXX They should
probably be diagnosed.) """
# abandon query parameters
path = path.split('?', 1)[0]
path = path.split('#', 1)[0]
path = posixpath.normpath(urllib.unquote(path))
words = path.split('/')
words = filter(None, words)
path = os.getcwd()
for word in words:
drive, word = os.path.splitdrive(word)
head, word = os.path.split(word)
if word in (os.curdir, os.pardir):
continue
path = os.path.join(path, word)
return path def copyfile(self, source, outputfile):
"""Copy all data between two file objects. The SOURCE argument is a file object open for reading
(or anything with a read() method) and the DESTINATION
argument is a file object open for writing (or
anything with a write() method). The only reason for overriding this would be to change
the block size or perhaps to replace newlines by CRLF
-- note however that this the default server uses this
to copy binary data as well. """
shutil.copyfileobj(source, outputfile) def guess_type(self, path):
"""Guess the type of a file. Argument is a PATH (a filename). Return value is a string of the form type/subtype,
usable for a MIME Content-type header. The default implementation looks the file's extension
up in the table self.extensions_map, using application/octet-stream
as a default; however it would be permissible (if
slow) to look inside the data to make a better guess. """ base, ext = posixpath.splitext(path)
if ext in self.extensions_map:
return self.extensions_map[ext]
ext = ext.lower()
if ext in self.extensions_map:
return self.extensions_map[ext]
else:
return self.extensions_map[''] if not mimetypes.inited:
mimetypes.init() # try to read system mime.types
extensions_map = mimetypes.types_map.copy()
extensions_map.update({
'': 'application/octet-stream', # Default
'.py': 'text/plain',
'.c': 'text/plain',
'.h': 'text/plain',
}) def test(HandlerClass=SimpleHTTPRequestHandler,
ServerClass=BaseHTTPServer.HTTPServer):
BaseHTTPServer.test(HandlerClass, ServerClass) if __name__ == '__main__':
test()
simple HTTP server with upload的更多相关文章
- Server Develop (九) Simple Web Server
Simple Web Server web服务器hello world!-----简单的socket通信实现. HTTP HTTP是Web浏览器与Web服务器之间通信的标准协议,HTTP指明了客户端如 ...
- System.Web.HttpContext.Current.Server.MapPath("~/upload/SH") 未将对象引用设置为实例对象
做项目的时候,System.Web.HttpContext.Current.Server.MapPath("~/upload/SH") 获取路径本来这个方法用的好好的 因为需要 ...
- Simple Rtmp Server的安装与简单使用
Simple Rtmp Server是一个国人编写的开源的RTMP/HLS流媒体服务器. 功能与nginx-rtmp-module类似, 可以实现rtmp/hls的分发. 有关nginx-rtmp-m ...
- Creating A Simple Web Server With Golang
原文:https://tutorialedge.net/post/golang/creating-simple-web-server-with-golang/ -------------------- ...
- Build Simple HTTP server
1. The server just support POST&PUT method 2. It is a Python server, and save upload files in sp ...
- Bonobo Git Server (Simple git server for Windows.) 测试备忘
Bonobo Git Server是一款Windows上的Git Server,它使用IIS即可,走的是Http协议,只要简单的安装就能使用,但是因为我的项目大小有1.35GB在 push 的时候一直 ...
- Chapter 1: A Simple Web Server
这算是一篇读书笔记,留着以后复习看看. Web Server又称为Http Server,因为它使用HTTP协议和客户端(一般是各种各样的浏览器)进行通信. 什么是HTTP协议呢? HTTP协议是基于 ...
- A Simple Web Server
介绍 在过去20几年里,网络已经在各个方面改变了我们的生活,但是它的核心却几乎没有什么改变.多数的系统依然遵循着Tim Berners-Lee在上个世纪发布的规则.大多数的web服务器都在用同样的方式 ...
- python server
#!/usr/bin/env python #coding=utf-8 # modifyDate: 20120808 ~ 20120810 # 原作者为:bones7456, http://li2z. ...
随机推荐
- Apple Pay编程指导
1.About Apple PayApple Pay是一种移动支付技术,让使用者把它们对真实的物品和服务的支付信息以一种方便和安全的方式给你. 对于在app中给出的数字物品和服务,可查看In-App ...
- ASP.NET MVC4在View中调用当前Controller中的方法
调用当前Controller中的方法 @{ ((HomeController)ViewContext.Controller).Method1(); } 调用静态方法 @{ SomeClass.Meth ...
- javascript使用百度地图api和html5特性获取浏览器位置
<!DOCTYPE html><html><head> <meta charset="utf-8"> <title>&l ...
- Spring编码过滤器:解决中文乱码
Spring编码过滤器:解决中文乱码 针对问题: 前台JSP页面和JAVA代码中使用了不同的字符集进行编码的时候就会出现表单提交的数据或者上传/下载中文名称文件出现乱码的问题: 解决方案: web.x ...
- MAC VNC SSH roo用户开通
第一步:ssh: user@xxx.xxx.xxx 第二步:开启VNC 开启VNC共享桌面: sudo /System/Library/CoreServices/RemoteManagement/A ...
- wix toolset 用wixui 默认中文
light.exe .\test.wixobj -ext WixUIExtension -ext WixUtilExtension -cultures:zh-CN
- 20145335郝昊《java程序设计》第7周学习总结
20145335郝昊 <Java程序设计>第7周学习总结 教材学习内容总结 认识时间与日期 格林威治标准时间:简称GMT时间,参考格林威治皇家天文台的标准太阳时间. 世界时:简称UT,借由 ...
- Alluxio集成Hadoop
准备工作 为了运行Alluxio集群在多个机器上,必须部署Alluxio服务到这些机器上.可以下载伴随特定Hadoop版本的二进制AlLxio包,也可以从Alluxio源码中编译. 当从源码中编译时, ...
- uboot下ext4ls的用法
列出sd卡的第一个分区里/bin目录下的内容,示例如下: ext4ls mmc 0:1 /bin
- [BZOJ2809]dispatching
Description 在一个忍者的帮派里,一些忍者们被选中派遣给顾客,然后依据自己的工作获取报偿.在这个帮派里,有一名忍者被称之为 Master.除了 Master以外,每名忍者都有且仅有一个上级. ...