十八.Python模擬FTP檔案上傳
阿新 • • 發佈:2019-01-11
Python 模擬FTP斷點續傳併發伺服器
#配置檔案
#伺服器配置檔案
[server_config] ip=127.0.0.1 port=8006 buffersize=1024 encoding=utf-8
#伺服器使用者資料
[tom] username=tom password=123456 [alex] username=alex password=123456
#FTP伺服器程式碼
#程式入口 import optparse import sys,os #os.path.dirname 獲取檔案的資料夾路徑 path=os.path.dirname(os.path.dirname(os.path.abspath(__file__))) sys.path.append(path) from core import main class ftt_server: def __init__(self): self.option = optparse.OptionParser() self.option.add_option("-i", "--ip", dest="ip") self.option.add_option("-p", "--port", dest="port") self.opt, self.args = self.option.parse_args() self.one() def one(self): main.main(self.opt, self.args) if __name__=="__main__": ftt_server()
#伺服器監聽程式 import socketserver import optparse import configparser import os from core import server class main(): def __init__(self,opt,args): args=args self.option=opt self.config=configparser.ConfigParser() self.config.read(os.path.dirname(os.path.dirname(__file__))+"/conf/config.ini") self.server=server self.BaseDir=os.path.dirname(os.path.dirname(__file__)) self.validate(opt, args) def validate(self, options, args): cmd=args[0] if hasattr(self,cmd): fun=getattr(self,cmd) fun() def start(self): ip=self.option.ip port=self.option.port if ip=="": ip=self.getConfig("server_config","ip") if port=="": port=self.getConfig("server_config","port") print("server start Successful!") self.sock_ser=socketserver.ThreadingTCPServer((ip,int(port)),self.server.server_handler) self.sock_ser.serve_forever() def help(self): pass def getConfig(self,section,attribute): return self.config.read(section,attribute)
#伺服器主程式 import socketserver import configparser import os import json import sys class server_handler(socketserver.BaseRequestHandler): def handle(self): self.config_name="server_config" self.BaseDir=os.path.dirname(os.path.abspath(os.path.dirname(__file__))) self.config_Path=os.path.join(self.BaseDir,"conf","config.ini") self.user_config=os.path.join(self.BaseDir,"conf","user.ini") self.buffersize=int(self.getIni(self.config_Path,self.config_name,"buffersize")) self.encoding=self.getIni(self.config_Path,self.config_name,"encoding") self.currenSize=0 data = self.request.recv(self.buffersize).decode(self.encoding) data = json.loads(data) print(data) fun = data["action"] if fun=="login": con=configparser.ConfigParser() con.read(self.user_config) if con.has_section(data["user"]): if con.get(data["user"],"password")==data["password"]: self.currenDir=data["user"] self.request.sendall("504".encode("utf-8")) self.name=data["user"] self.home=os.path.join(self.BaseDir, "home",data["user"]) self.currenDir=self.home self.interception() else: self.request.sendall("404".encode("utf-8")) def getIni(self,path,section,attribute): conf = configparser.ConfigParser() conf.read(path) return conf.get(section, attribute) #互動 def interception(self): while 1: print("wait recv....") data=self.request.recv(self.buffersize) data=json.loads(data) print(data) fun=data["action"] if hasattr(self,fun): func=getattr(self,fun) func(**data) else: self.request.sendall("400".encode("utf-8")) #cd資料夾切換功能 def cd(self,**kwargs): position=kwargs["position"] if position=="../": self.currenDir =os.path.dirname(self.currenDir) else: self.currenDir=os.path.join(self.currenDir,position) self.request.sendall(os.path.basename(self.currenDir).encode(self.encoding)) #建立資料夾功能 def mkdir(self,**kwargs): print(kwargs) position=kwargs["position"] mkfile=os.path.join(self.currenDir,position) try: if "/" in position or "\\" in position: os.makedirs(mkfile) else: os.mkdir(mkfile) except Exception as e: self.request.sendall("605".encode(self.encoding)) self.request.sendall("606".encode(self.encoding)) #顯示當前資料夾內容 def ls(self,**kwargs): dir_con=os.listdir(self.currenDir) self.request.sendall(str(dir_con).encode("utf-8")) #檔案斷點續傳功能 def put(self,**kwargs): file_name=kwargs["file_name"] file_size=kwargs["file_size"] target=kwargs["target"] self.target_file=os.path.join(self.currenDir,target,file_name) if os.path.exists(self.target_file): self.currenSize=os.stat(self.target_file).st_size if self.currenSize>=file_size: self.request.sendall("801".encode(self.encoding)) return else: self.request.sendall("802".encode(self.encoding)) data=self.request.recv(self.buffersize).decode(self.encoding) if data=="Y": f = open(self.target_file, "ab") self.request.sendall(str(self.currenSize).encode(self.encoding)) else: f = open(self.target_file, "wb") else: f = open(self.target_file, "wb") self.request.sendall("803".encode("utf-8")) while self.currenSize<file_size: data=self.request.recv(self.buffersize) f.write(data) self.currenSize+=len(data) self.progess(self.currenSize, file_size) #檔案上傳進度 def progess(self,curren,total): rate = int(curren / total * 100) if rate > 0: st=sys.stdout st.write("%s%% %s \r\n"%(rate,"*"*rate)) st.flush() if rate==100: print("upload finish!")
#FTP客戶端
#配置檔案
[client_config] buffer_size=1024
#客戶端程式碼
#FTP客戶端程式 from socket import * import sys,os import optparse import json import configparser path=os.path.dirname(os.path.dirname(__file__)) sys.path.append(path) #狀態字典 dicts={"504":"登陸成功!", "404":"使用者或者密碼有誤!登陸失敗!", "400":"Input Error", "606":"create success", "605":"create fail", "801":"the file is existing", "802":"the file is existing,but not enough", "803":"the file start upload..." } class client_handler: def __init__(self): self.option=optparse.OptionParser() self.option.add_option("-i", "--ip", dest="ip") self.option.add_option("-p", "--port", dest="port") self.option.add_option("-u", "--user", dest="username") self.option.add_option("-P", "--password", dest="password") self.conf = configparser.ConfigParser() self.Base_Dir=os.path.dirname(os.path.abspath(os.path.dirname(__file__))) self.buffersize= int(self.bufferSize()) self.size_file=0 options, args = self.option.parse_args() self.task(options,args) def task(self, options, args): port=options.port if int(port)>0 and int(port)<65535: self.make_connection(options,args) else: exit("the port is in 0 and 65535!") def make_connection(self, options, args): self.sclient = socket(AF_INET, SOCK_STREAM) self.sclient.connect((options.ip, int(options.port))) self.login() def login(self): name=input("請輸入使用者名稱>>") password=input("請輸入密碼>>") self.json = {"action": "login", "user": name, "password": password} self.sclient.send(json.dumps(self.json).encode("utf-8")) data=self.sclient.recv(self.buffersize).decode("utf-8") # print(data) if data=="504": self.name=name print(dicts[data]) while 1: code=input("[%s]"%self.name) cmd_list=code.split() if hasattr(self,cmd_list[0]): fun=getattr(self,cmd_list[0]) fun(*cmd_list) else: print(dicts[data]) def bufferSize(self): self.conf_path=os.path.join(self.Base_Dir,"conf","config.ini") self.conf.read(self.conf_path) return self.conf.get("client_config", "buffer_size") def put(self,*cmd_list): # print("put...") action,location,target=cmd_list file_name=os.path.basename(location) file_size=os.stat(location).st_size data={"action":action, "file_name":file_name, "file_size":file_size, "target":target} self.sclient.sendall(json.dumps(data).encode("utf-8")) data=self.sclient.recv(self.buffersize).decode("utf-8") self.parseNum(data) if data=="801": return elif data=="802": choice=input("the file is existing,but not enough,is continue?<Y/N>") if choice.upper()=="Y": self.sclient.sendall(choice.upper().encode("utf-8")) self.size_file =int(self.sclient.recv(self.buffersize).decode("utf-8")) else: self.sclient.sendall(choice.upper().encode("utf-8")) elif data=="803": pass f=open(location,"rb") f.seek(self.size_file) while self.size_file<file_size: fdata=f.read(self.buffersize) self.sclient.sendall(fdata) self.size_file+=len(fdata) self.progess(self.size_file, file_size) def cd(self,*cmd_list): # print("cd...") action,position=cmd_list data={"action":action, "position":position} data=json.dumps(data) self.sclient.sendall(data.encode("utf-8")) data=self.sclient.recv(self.buffersize).decode("utf-8") self.name=data def ls(self,*cmd_list): action=cmd_list[0] data={"action":action} data=json.dumps(data) self.sclient.sendall(data.encode("utf-8")) con=self.sclient.recv(self.buffersize).decode("utf-8") con=list(con) for i in con: print(i,end="\r") def mkdir(self,*cmd_list): print("mkdir...") action,position=cmd_list data={"action":action, "position":position } data=json.dumps(data) self.sclient.sendall(data.encode("utf-8")) con=self.sclient.recv(self.buffersize).decode("utf-8") print(dicts[con]) def parseNum(self,st): print(dicts[st]) def progess(self,curren,total): rate=int(curren/total*100) if rate > 0: st=sys.stdout st.write("%s%% %s\r\n"%(rate,"*"*rate)) st.flush() if rate==100: print("upload finish!") #程式入口 if __name__=="__main__": client_handler()
啟動
#伺服器啟動 python ftp_server start -i 127.0.0.1 -p 8006 #客戶端啟動 python ftp_client -i 127.0.0.1 -p 8006