用Python手寫檔案伺服器

這是一個用Python寫的迷你檔案伺服器, 有在Ubuntu上測試過python2.7和python3.4版都可以使用。

如果要接受所有來源的ThisServerIp請使用0.0.0.0作為Server位址
如果要當作一般的網站ThisServerPort請使用80
要提供下載的檔案請把絕對路徑寫在DownloadFilePath1和DownloadFilePath2上

執行的方法

1. For Windows
python.exe MyServer.py

2. For Ubuntu
python MyServer.py

測試用URL

http://127.0.0.1:8080/GetFileInfo
http://127.0.0.1:8080/GetFileInfo?name=file1
http://127.0.0.1:8080/GetFileInfo?name=file2
http://127.0.0.1:8080/DownloadFile1
http://127.0.0.1:8080/DownloadFile2

GetFileInfo沒有指定參數name的時候會回應json格式的資訊
DownloadFile1, DownloadFile2是直接下載script指定的檔案

檔案伺服器MyServer.py

#!/usr/bin/python
# coding=utf-8
import os.path, sys
import hashlib, json, shutil

if sys.version_info >= (3,0):
    from urllib.parse import parse_qs
    from http.server import SimpleHTTPRequestHandler,BaseHTTPRequestHandler,HTTPServer
else:
    from urlparse import parse_qs
    from BaseHTTPServer import BaseHTTPRequestHandler,HTTPServer
    from SimpleHTTPServer import SimpleHTTPRequestHandler

#####################################################################
# Please change those setting by your workstation
#####################################################################
ThisServerIp  = "127.0.0.1"
ThisServerPort = 8080
DownloadFilePath1 = "/home/user/test1"
DownloadFilePath2 = "/home/user/test2"
#####################################################################

ThisServerAddress = (ThisServerIp, ThisServerPort)

def getFileMd5(path):
    f = open(path,"rb")
    ret = hashlib.md5(f.read()).hexdigest()
    f.close()
    del f
    return ret

def getFileSize(path):
    return os.path.getsize(path)

def responseJson(hdl, data):
    hdl.send_response(200)
    hdl.send_header("Content-type", "application/json")
    hdl.end_headers()
    hdl.wfile.write(json.dumps(data).encode("utf-8"))

def responseFile(hdl, path):
    f = open(path, "rb")
    fs = os.fstat(f.fileno())
    hdl.send_response(200)
    hdl.send_header("Content-type", "application/octet-stream")
    hdl.send_header("Content-Length", str(fs[6]))
    hdl.send_header("Last-Modified", hdl.date_time_string(fs.st_mtime))
    hdl.end_headers()
    shutil.copyfileobj(f, hdl.wfile)
    f.close()
    del f

class MyHandler(BaseHTTPRequestHandler):
    def do_GET(hdl):
        hdl.log_message("from %s req %s", hdl.client_address, hdl.path)
        try:
            if hdl.path.startswith("/GetFileInfo"):
                filename = ""
                argpos = hdl.path.find('?')
                if -1 != argpos:
                    urldict = parse_qs(hdl.path[argpos+1:])
                    if "name" in urldict:
                        filename = "".join(urldict["name"])
                hdl.log_message("name=\'%s\'", filename)
                try:
                    if filename == "file1":
                        data = {
                            "statusCode" : "000",
                            "File_URL" : ("http://%s:%d/DownloadFile1" % ThisServerAddress),
                            "File_Size" : getFileSize(DownloadFilePath1),
                            "MD5_SUM" : getFileMd5(DownloadFilePath1)
                        }
                    elif filename == "file2":
                        data = {
                            "statusCode" : "000",
                            "File_URL" : ("http://%s:%d/DownloadFile2" % ThisServerAddress),
                            "File_Size" : getFileSize(DownloadFilePath2),
                            "MD5_SUM" : getFileMd5(DownloadFilePath2)
                        }
                    else:
                        data = {"statusCode" : "404"}
                        hdl.log_error("not found the file '%s'", filename)
                except:
                    data = {"statusCode" : "404"}
                    hdl.log_error("GetFileInfo Unexpected error: %s", sys.exc_info())
                responseJson(hdl, data)
                return None
            elif hdl.path == "/DownloadFile1":
                responseFile(hdl, DownloadFilePath1)
            elif hdl.path == "/DownloadFile2":
                responseFile(hdl, DownloadFilePath2)
            else:
                hdl.log_error("Invalid access: %s", sys.exc_info())
                hdl.send_error(404)
        except:
            hdl.log_error("Unexpected error: %s", sys.exc_info())
            hdl.send_error(404)
            return None

httpd = HTTPServer(ThisServerAddress, MyHandler)
sa = httpd.socket.getsockname()
print ("Serving HTTP on %s port %d..." % (sa[0], sa[1]))
httpd.serve_forever()

參考資料

https://blog.gtwang.org/web-development/python-simplehttpserver-web-server/

留言