启动一个支持文件上传的HTTP-Server
Python实现,源码来自网络,代码内部有作者信息。
HTTP方式共享文件,对于不需要用户名和密码验证的系统非常方便。通过浏览器就可以实现文件上传和下载。非常适合用作测试系统的脚手架。
对于系统使用curl命令行也可以轻松实现文件上传。wget实现文件下载。
- nohup python SimpleHTTPServerWithUpload.py & # 在8088端口启动这个http-server服务
- #!/usr/bin/env python
- """Simple HTTP Server With Upload.
- This module builds on BaseHTTPServer by implementing the standard GET
- and HEAD requests in a fairly straightforward manner.
- """
- __version__ = "0.1"
- __all__ = ["SimpleHTTPRequestHandler"]
- __author__ = "bones7456"
- __home_page__ = "http://li2z.cn/"
- import os
- import posixpath
- import BaseHTTPServer
- import urllib
- import cgi
- import shutil
- import mimetypes
- import re
- 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<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 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)
- 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>\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:
- 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()
启动一个支持文件上传的HTTP-Server的更多相关文章
- java nio 写一个完整的http服务器 支持文件上传 chunk传输 gzip 压缩 使用过程 和servlet差不多
java nio 写一个完整的http服务器 支持文件上传 chunk传输 gzip 压缩 也仿照着 netty处理了NIO的空轮询BUG 本项目并不复杂 代码不多 ...
- RPC基于http协议通过netty支持文件上传下载
本人在中间件研发组(主要开发RPC),近期遇到一个需求:RPC基于http协议通过netty支持文件上传下载 经过一系列的资料查找学习,终于实现了该功能 通过netty实现文件上传下载,主要在编解码时 ...
- Openresty + nginx-upload-module支持文件上传
0. 说明 这种方式其实复杂,麻烦!建议通过这个方式搭建Openresty文件上传和下载服务器:http://www.cnblogs.com/lujiango/p/9056680.html 1. 包下 ...
- springmvc学习笔记--支持文件上传和阿里云OSS API简介
前言: Web开发中图片上传的功能很常见, 本篇博客来讲述下springmvc如何实现图片上传的功能. 主要讲述依赖包引入, 配置项, 本地存储和云存储方案(阿里云的OSS服务). 铺垫: 文件上传是 ...
- 让nginx支持文件上传的几种模式
文件上传的几种不同语言和不同方法的总结. 第一种模式 : PHP 语言来处理 这个模式比较简单, 用的人也是最多的, 类似的还有用 .net 来实现, jsp来实现, 都是处理表单.只有语言的差别, ...
- 让UpdatePanel支持文件上传(2):服务器端组件 .
我们现在来关注服务器端的组件.目前的主要问题是,我们如何让页面(事实上是ScriptManager控件)认为它接收到的是一个异步的回送?ScriptManager控件会在HTTP请求的Header中查 ...
- 让UpdatePanel支持文件上传(1):开始 .
UpdatePanel从一开始就无法支持AJAX的文件上传方式.Eilon Lipton写了一篇文章解释了这个问题的原因.文章中提供了两个绕开此问题的方法: 将“上传”按钮设为一个传统的PostBac ...
- 配置servlet支持文件上传
Servlet3.0为Servlet添加了multipart配置选项,并为HttpServletRequest添加了getPart和getParts方法获取上传文件.为了使Servlet支付文件上传需 ...
- 测试平台系列(92) 让http请求支持文件上传
大家好~我是米洛! 我正在从0到1打造一个开源的接口测试平台, 也在编写一套与之对应的教程,希望大家多多支持. 欢迎关注我的公众号米洛的测开日记,获取最新文章教程! 回顾 上一节呢,我们编写了oss的 ...
随机推荐
- 跟着百度学PHP[14]-COOKIE的应用/网站登陆案例完整案例
先在数据库当中创建以下数据: mysql> create table user( -> id int not null auto_increment, ) not null default ...
- 让一个 csproj 项目指定多个开发框架[转]
原贴:https://walterlv.gitee.io/post/configure-projects-to-target-multiple-platforms.html 可移植类库.共享项目..N ...
- OpenERP report doesn't work
1. When you have used OpenOffice edited one of reports,it has stored the report's banary data is da ...
- 转 java调用php的webService
1.首先先下载php的webservice包:NuSOAP,自己到官网去下载,链接就不给出来了,自己去google吧 基于NoSOAP我们写了一个php的webservice的服务端,例子如下: ...
- Android最流行的网络框架(原创)
Android程序最重要的模块就是网络部分,如何从网络上下载数据,如何将处理过的数据上传至网络,往往是android程序的关键环节. Android原生提供基于HttpClient和Ht ...
- java 遍历String
Java字符串是一系列的Unicode字符序列,但是,它却常常被误认为是char序列.于是,我们经常这样来遍历字符串: package testchar; public class TestChar2 ...
- BlockingQueue(阻塞队列)分析
如果读者还有一点印象,我们在实现线程池时,用了队列这种数据结构来存储接收到的任务,在多线程环境中阻塞队列是一种非常有用的队列,在介绍BlockingQueue之前,我们先解释一下Queue接口. Qu ...
- VC++ Debug内存值
Memory Values If you're using the debug heap, memory is initialized and cleared with special values. ...
- reactjs中props和state最佳实践
http://blog.csdn.net/dangnian/article/details/50998981
- 使用HTML5构建iOS原生APP(2)
本文转载至 http://ju.outofmemory.cn/entry/18807 有时候我们在内嵌的webview中希望点击一个链接之后,触发iOS原生事件,而不是webview内页面跳转(因为w ...