Python实现简易文件服务器 包含上传下载删除新建目录功能
2017-09-27 17:33
1271 查看
#!/usr/bin/python # -*- coding: UTF-8 -*- ''' kysec_set -n exectl -v verified ./HttpServerWithUpload.py nohup python HttpServerWithUpload.py > /dev/null 2>&1 & ''' __version__ = "0.6" __all__ = ["SimpleHTTPRequestHandler"] import os, sys, platform, socket, struct, json import posixpath import BaseHTTPServer import urllib, urllib2 import urlparse import cgi import shutil import mimetypes try: from cStringIO import StringIO except ImportError: from StringIO import StringIO import time from SocketServer import ThreadingMixIn import re import threading import md5, hashlib def get_ip_address(ifname=None): if sys.platform == 'win32': return socket.getaddrinfo(socket.gethostname(), None, socket.AF_INET, socket.SOCK_DGRAM)[-1][4][0] else: import fcntl s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) return socket.inet_ntoa(fcntl.ioctl( s.fileno(), 0x8915, # SIOCGIFADDR struct.pack('256s', ifname[:15]) )[20:24]) class GetWanIp: def getip(self): try: myip = get_ip_address(ifname="eth0") except Exception, e: #print "eth0"+str(e) myip = "127.0.0.1" return myip def visit(self ,url): import requests content = requests.get('http://ipinfo.io').content print getTimeNow()+content json_content = json.loads(content) return json_content["ip"] def getTimeNow(): return time.strftime("%Y-%m-%d %H:%M:%S",time.localtime())+"-->" def showTips(): port = 1234 try: port = int(sys.argv[1]) print getTimeNow()+'Please visit files or dirs use Chrome Browser:http://'+GetWanIp().getip()+':'+str(port) except Exception, e: print getTimeNow()+'You have not give a port, plase use Chrome Browser:http://'+GetWanIp().getip()+':'+str(port) if not 1024 < port < 65535: port = 1234 return ('', port) serveraddr = showTips() def sizeof_fmt(num): if num==0: return '0.0bytes' for x in ['bytes', 'KB', 'MB', 'GB']: if num < 1024.0: return "%3.1f%s" % (num, x) num /= 1024.0 return "%3.1f%s" % (num, 'TB') def modification_date(filename): if os.path.isfile(filename): return time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(os.path.getmtime(filename))) elif os.path.isdir(filename): return time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(os.path.getmtime(filename))) else: return "" def sumfile(fobj): m = md5.new() while True: d = fobj.read(8096) if not d: break m.update(d) return m.hexdigest() def md5sum(fname): if fname == '-': ret = sumfile(sys.stdin) else: try: f = file(fname, 'rb') except: return '' ret = sumfile(f) f.close() return ret class SimpleHTTPRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler): server_version = "SimpleHTTP/" + __version__ def do_buildHeadMessage(self,f,title): f.write('<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"><html>\n<head><STYLE><!--H1 {font-family: Tahoma, Arial, sans-serif;color: white;background-color: #525D76;font-size: 22px;}H2 {font-family: Tahoma, Arial, sans-serif;color: white;background-color: #525D76;font-size: 16px;}H3 {font-family: Tahoma, Arial, sans-serif;color: white;background-color: #525D76;font-size: 14px;}BODY {font-family: Tahoma, Arial, sans-serif;color: black;background-color: white;}B {font-family: Tahoma, Arial, sans-serif;color: white;background-color: #525D76;}P {font-family: Tahoma, Arial, sans-serif;background: white;color: black;font-size: 12px;}A {color: black;}A.name {color: black;}HR {color: #525D76;}--></STYLE>') f.write('<title>%s</title></head>\n' % title) ''' 原则是用到再使用,用完立马还原 两种情况会用到 界面显示;处理中遇到中文 ''' def do_utf82gbk(self,sts): osType = platform.system() if osType == "Windows": sts = sts.decode('utf-8').encode('gbk') print "do_utf82gbk char:" + sts return sts else: sts = sts return sts def do_gbk2utf8(self,sts): osType = platform.system() if osType == "Windows": sts = sts.decode('gbk').encode('utf-8') #print "do_gbk2utf8 char:" + sts return sts else: sts = sts return sts def do_GET(self): """Serve a GET request.""" if("?delete=" in self.path): r, info = self.deal_delFile(self.path) self.showMessage(r,info) elif("?makedir=" in self.path): r,info = self.deal_makeDir(self.path) self.showMessage(r,info) else: f = self.send_head() if f: try: self.copyfile(f, self.wfile) finally: f.close() def do_HEAD(self): """Serve a HEAD request.""" f = self.send_head() if f: f.close() def showMessage(self,r,info): f = StringIO() self.do_buildHeadMessage(f,'消息提示') f.write('<body>\n<h1>消息提示</h1>\n<HR size="1" noshade="noshade">\n') if r: f.write('<strong>成功:</strong>\n<font color="GREEN">'+info+'</font>\n') else: f.write('<strong>失败:</strong>\n<font color="RED">'+info+'</font>\n') f.write(' <a href="javascript:" onclick="self.location=document.referrer;">返回</a>\n') f.write(" <input type=\"button\" value=\"返回首页\" onClick=\"location='/'\">\n<HR size=\"1\" noshade=\"noshade\">\n<h2>Powered By kanbuxiaqu@outlook.com</h2>\n</body>\n</html>") length = f.tell() f.seek(0) self.send_response(200) self.send_header("Content-type", "text/html; charset=%s" % "utf-8") self.send_header("Content-Length", str(length)) self.end_headers() if f: self.copyfile(f, self.wfile) f.close() def do_POST(self): r, info = self.deal_post_data() self.showMessage(r,info) def deal_makeDir(self,path): dirname = path.split('?makedir=',1)[1] dirpath = self.translate_path(self.path) path = posixpath.normpath(urllib.unquote(dirpath+self.do_utf82gbk(urllib.unquote(dirname)))) path=path.strip() path=path.rstrip("\\") isExists=os.path.exists(path) if not isExists: os.makedirs(path) return (True,self.do_gbk2utf8(path)+" 创建成功") else: return (False,self.do_gbk2utf8(path)+" 目录已存在") def deal_delFile(self,path): if("?delete=" in path): dirname = path.split('?delete=',1)[1] dirpath = self.translate_path(self.path) path = posixpath.normpath(urllib.unquote(dirpath+dirname)) path=path.strip() path=path.rstrip("\\") if os.path.isfile(path): try: os.remove(path) return (True, "文件删除成功.") except Exception, e: return (False, "文件删除失败.\n"+e) elif os.path.isdir(path): for item in os.listdir(path): itempath = os.path.join(path,item) self.deal_delFile(itempath) try: os.rmdir(path) return (True, "文件删除成功.") except Exception,e: return (False, "文件删除失败.\n"+e) 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 not boundary 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) try: fn = os.path.join(path, self.do_utf82gbk(fn[0])) except Exception, e: return (False, "文件名请不要用中文,或者使用IE上传中文名的文件。"+e) 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!" % self.do_gbk2utf8(fn)) else: out.write(preline) preline = line return (False, "Unexpect Ends of data.") def send_head(self): path = self.translate_path(self.path) f = None if os.path.isdir(path): parts = urlparse.urlsplit(self.path) if not parts.path.endswith('/'): # redirect browser - doing basically what apache does self.send_response(301) new_parts = (parts[0], parts[1], parts[2] + '/', parts[3], parts[4]) new_url = urlparse.urlunsplit(new_parts) self.send_header("Location", new_url) 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 try: 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 except: f.close() raise def list_directory(self, path): 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)) self.do_buildHeadMessage(f,'文件列表 '+self.do_gbk2utf8(displaypath)) f.write("<body>\n<h1>文件列表 %s</h1>\n" % self.do_gbk2utf8(displaypath)) f.write('<HR size="1" noshade="noshade">\n') f.write('<table><tr><td>') f.write("<input type=\"button\" value=\"返回\" onClick=\"javascript:history.back(-1);\"></td><td>") f.write("<form ENCTYPE=\"multipart/form-data\" method=\"post\">") f.write("<input name=\"file\" type=\"file\"/>") f.write("<input type=\"submit\" value=\"上传\"/>") f.write("</form></td><td>") f.write('<form method="get">') f.write('<input type="text" name="makedir" />') f.write('<input type="submit" value="新建文件夹" /> ') f.write("<input type=\"button\" value=\"返回首页\" onClick=\"location='/'\">") f.write('</form></td></tr></table>') f.write('<HR size="1" noshade="noshade">') f.write('<table border=0 width="100%" cellspacing="0" cellpadding="5" align="center" style="overflow: scroll;word-break: keep-all"><tr bgcolor="#00DB00"><td>序号</td><td>文件名</td><td>文件大小</td><td>文件创建时间</td><td>操作</td></tr>') idn=1 for name in list: fullname = os.path.join(path, name) colorName = linkname = name # Append / for directories or @ for symbolic links filename = os.getcwd() + displaypath + name filesize = 0 if os.path.isfile(filename): filesize = os.path.getsize(filename) elif os.path.isdir(filename): filesize = os.path.getsize(filename) else: print getTimeNow()+'The file can`t read it:'+filename if(idn%2==0): f.write('<tr>') else: f.write('<tr bgcolor="#eeeeee">') if os.path.isdir(fullname): colorName = '<span style="background-color: #CEFFCE;">' + name + '/</span>' linkname = name + "/" if os.path.islink(fullname): colorName = '<span style="background-color: #FFBFFF;">' + name + '@</span>' # Note: a link to a directory displays with @ and links with / f.write( '<td width="10%%">%d</td><td width="40%%"><a href="%s">%s</a></td><td width="20%%">%s</td><td width="20%%">%s</td><td><a href="%s">删除</a></td></tr>\n' % (idn,urllib.quote(linkname), self.do_gbk2utf8(colorName), sizeof_fmt(filesize), modification_date(filename),"?delete="+urllib.quote(linkname))) idn = idn+1 f.write('</table>\n<HR size="1" noshade="noshade">\n<h2>Powered By kanbuxiaqu@outlook.com</h2>\n</body>\n</html>\n') length = f.tell() f.seek(0) self.send_response(200) self.send_header("Content-type", "text/html; charset=%s" % "utf-8") self.send_header("Content-Length", str(length)) self.end_headers() return f def translate_path(self, path): # abandon query parameters path = path.split('?',1)[0] path = path.split('#',1)[0] # Don't forget explicit trailing slash when normalizing. Issue17324 trailing_slash = path.rstrip().endswith('/') path = posixpath.normpath(urllib.unquote(path)) words = path.split('/') words = filter(None, words) path = os.getcwd() for word in words: if os.path.dirname(word) or word in (os.curdir, os.pardir): # Ignore components that are not a simple file/directory name continue path = os.path.join(path, word) if trailing_slash: path += '/' return path def copyfile(self, source, outputfile): shutil.copyfileobj(source, outputfile) def guess_type(self, path): 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', }) class ThreadingServer(ThreadingMixIn, BaseHTTPServer.HTTPServer): pass def test(HandlerClass = SimpleHTTPRequestHandler, ServerClass = BaseHTTPServer.HTTPServer): BaseHTTPServer.test(HandlerClass, ServerClass) if __name__ == '__main__': # test() # 单线程 # srvr = BaseHTTPServer.HTTPServer(serveraddr, SimpleHTTPRequestHandler) # 多线程 srvr = ThreadingServer(serveraddr, SimpleHTTPRequestHandler) srvr.serve_forever()
相关文章推荐
- 调用hadoop api实现文件的上传、下载、删除、创建目录和显示功能
- JAVA实现FTP服务器文件的上传,下载,删除功能
- C#实现Ftp各种操作(上传,下载,删除文件,创建目录,删除目录,获得文件列表)
- Java实现FTP服务器的上传、下载、删除、查看文件列表
- Microsoft .NET Framework 2.0对文件传输协议(FTP)操作(上传,下载,新建,删除,FTP间传送文件等)实现汇总1
- Microsoft .NET Framework 2.0对文件传输协议(FTP)操作(上传,下载,新建,删除,FTP间传送文件等)实现汇总1
- 使用.net FtpWebRequest 实现FTP常用功能 上传 下载 获取文件列表 移动 切换目录 改名 .
- Microsoft .NET Framework 2.0对文件传输协议(FTP)操作(上传,下载,新建,删除,FTP间传送文件等)实现汇总
- Java实现远程HDFS的文件操作(新建、上传、下载、删除)
- servlet实现文件上传、预览、下载、删除功能
- 使用递归方法实现,向FTP服务器上传整个目录结构、从FTP服务器下载整个目录到本地的功能
- Java实现远程HDFS的文件操作(新建、上传、下载、删除)
- Linux系统服务 6 ---- vsftpd服务的配置文件实现匿名登录上传下载和删除功能
- python实现上传下载文件功能
- .Net 2.0对文件传输协议(FTP)操作(上传,下载,新建,删除,FTP间传送文件等)实现汇总
- Microsoft .NET Framework 2.0对文件传输协议(FTP)操作(上传,下载,新建,删除,FTP间传送文件等)实现汇总1
- Microsoft .NET Framework 2.0对文件传输协议(FTP)操作(上传,下载,新建,删除,FTP间传送文件等)实现汇总1
- Microsoft .NET Framework 2.0对文件传输协议(FTP)操作(上传,下载,新建,删除,FTP间传送文件等)实现汇总1
- asp.net mvc导出excel文件先保存到服务器某个目录,然后再导出到客户端供客户下载功能的实现
- Microsoft .NET Framework 2.0对文件传输协议(FTP)操作(上传,下载,新建,删除,FTP间传送文件等)实现汇总1