老男孩Day8作業:FTP
阿新 • • 發佈:2018-02-28
bind 文件名 .py 客戶 txt pre 返回 獲取 有效
1、作業需求
開發簡單的FTP:
1. 用戶登陸
2. 上傳/下載文件
3. 不同用戶家目錄不同
4. 查看當前目錄下文件
5. 充分使用面向對象知識
2、流程圖
3、目錄結構
4、代碼區
bin目錄下的start.py程序執行文件
# -*- coding:utf-8 -*- # Author:D.Gray import os,sys BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) sys.path.append(BASE_DIR) from core import ftp_client fcstart_client.py= ftp_client.FTP_client()
# -*- coding:utf-8 -*- # Author:D.Gray import os,sys BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) sys.path.append(BASE_DIR) from core import ftp_server fs = ftp_server.FTP_server()start_server.py
conf目下的setting.py系統配置文件
# -*- coding:utf-8 -*-setting.py# Author:D.Gray import os,sys,socket BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) #IP地址和端口 IP_PORT = ("localhost",6969) #數據文件路徑 USER_FILE = BASE_DIR + r"\db\user.db" #用戶文件目錄 USER_HOME = BASE_DIR
core目錄下主程序文件
# -*- coding:utf-8 -*- # Author:D.Gray import os,sys,socketftp_client.pyfrom conf import setting from core import ftp_server from core import users class FTP_client(object): def __init__(self): self.client = setting.socket.socket() self.client.connect(setting.IP_PORT) self.user_obj = users.Users() self.help_info = { "get":"用於上傳文件,例如:get readme.txt 即 get 文件名", "put":"用於下載文件,例如:put readme.txt 即 put 文件名", ‘dir‘:"用於顯示當前目錄下文件或文件詳細信息 格式 ls " } if self.auth(): self.start() def auth(self): ‘‘‘ 用戶登錄驗證函數 :return: ‘‘‘ while True: username = input("請輸入用戶名>>>:").strip() pwd = input("請輸入用戶密碼>>>:").strip() auth_info = ‘auth %s %s‘%(username,pwd) #格式化輸出 auth 用戶名 密碼 self.client.send(auth_info.encode()) #將格式化後的內容發送給服務端 back_res = self.client.recv(1024).decode() if back_res == "ok": print(‘認證成功‘) user = self.user_obj.get_user(username) self.current_user = username self.current_pwd = pwd self.current_path = user[‘home‘] self.current_dir = back_res[1] return True elif back_res == "Not password": print("\033[31;1m密碼不正確\033[0m") else: print("\033[31;1m用戶不存在\033[0m") def start(self): ‘‘‘ 輸入指令上傳下載文件函數 :return: ‘‘‘ while True: user_input = input(‘%s>>>:‘%self.current_user).strip() if len(user_input) == 0:continue user_input = user_input.split() if user_input[0] == ‘q‘:break if hasattr(self,user_input[0]): func = getattr(self,user_input[0]) func(user_input) else: print("\033[31;1m請輸入有效指令\033[0m") continue def put(self,cmd): ‘‘‘ 從服務器端下載文件函數 :param cmd: :return: ‘‘‘ print(‘in the put:‘,cmd) send_server_info = ‘%s %s‘%(cmd[0],cmd[1]) #格式化輸出[‘方法‘,‘文件名‘] self.client.send(send_server_info.encode()) #將格式化輸出內容發送給服務器端 server_back = self.client.recv(1024).decode() #接收服務器回調結果 print("接收服務器回調信息:",server_back) if server_back == "302": print(‘\033[31;1m文件不存在\033[0m‘) else: file_totle_size = int(server_back) #從服務器端接收文件大小 print("您要下載的文件大小為:%sByte"%file_totle_size) self.client.send(‘可以開始下載了...‘.encode()) rever_file_size = 0 #接收到的文件大小 file_name_path = setting.USER_HOME + self.current_path + ‘\\user_home\\‘ + cmd[1] #print(file_name_path) with open(file_name_path,"wb") as f: while rever_file_size < file_totle_size: if file_totle_size - rever_file_size < 1024: #當剩余文件大小<1024 全部接收文件 size = file_totle_size - rever_file_size else: size = 1024 data = self.client.recv(size) #當剩余文件<1024全部接收文件,當剩余文件>1024每次只接收1024 rever_file_size += len(data) #每次接收數據時自動累計rever_file_size值 print("已接收%sByte"%rever_file_size) f.write(data) else: print(‘接受完畢‘) def get(self,cmd): ‘‘‘ 本地上次文件給服務器端 :param cmd: 接收用戶通過start函數輸入的操作指令 :return: ‘‘‘ print(cmd) file_path = setting.USER_HOME + self.current_path +‘\\user_home\\‘ + cmd[1] if os.path.isfile(file_path): file_totle_size = os.stat(file_path).st_size print(‘您要上傳文件大小為【%sByte】‘%file_totle_size) file_info = ‘%s %s %s‘%(cmd[0],cmd[1],file_totle_size) #格式化輸出[‘操作指令‘,‘文件名‘,‘文件大小‘] self.client.send(file_info.encode()) #將格式化輸出內容發送給服務器端 server_back = self.client.recv(1024).decode() #接收回調信息 if server_back == "300": print(‘可以上傳文件了...‘) send_file_size = 0 with open(file_path,‘rb‘) as f: while send_file_size != file_totle_size: if file_totle_size-send_file_size <= 1024: data = f.read(file_totle_size-send_file_size) send_file_size += file_totle_size - send_file_size else: data = f.read(1024) send_file_size += len(data) print("已上傳【%sByte】"%send_file_size) self.client.send(data) print("上傳成功") else: print(‘\033[31;1m文件不存在\033[0m‘) def dir(self,cmd): ‘‘‘ 查看服務端目錄文件信息 :param cmd: :return: ‘‘‘ print(cmd) send_server_info = ‘%s‘%cmd[0] #格式化輸出用戶指令 self.client.send(send_server_info.encode()) server_back = self.client.recv(1024).decode() #接收服務端回調 print("獲取服務端回調信息:%s"%server_back) self.client.send("ok".encode()) #發送給服務端‘ok‘ recv_size = 0 recv_data = b‘‘ while recv_size < int(server_back): data = self.client.recv(1024) recv_data += data recv_size = len(data) print(recv_size) else: print(recv_data.decode()) def help(self,cmd): ‘‘‘ 查看幫助文檔函數 :param cmd: :return: ‘‘‘ print(cmd) d = self.help_info print(d)
# -*- coding:utf-8 -*- # Author:D.Gray import os,sys,socket from conf import setting from core import ftp_client from core import users class FTP_server(object): def __init__(self): self.server = setting.socket.socket() self.server.bind(setting.IP_PORT) self.server.listen(5) self.user_obj = users.Users() #導入users文件並實例化Users類 self.start() def start(self): print("等待鏈接中...") while True: self.conn,self.addr = self.server.accept() print("一個新的鏈接:%s %s"%(self.conn,self.addr)) while True: self.data = self.conn.recv(1024) #接受客戶端格式化輸出內容 #print(‘data:‘,self.conn) if not self.data: print("客戶端斷開") break cmd_res = self.data.decode().split() #以列表形式獲取用戶輸入的[[方法名],[文件名]] cmd_action = cmd_res[0] #獲取方法名 #print(‘in the start獲取方法名:‘,cmd_action) if hasattr(self,cmd_action): #判斷用戶輸入的方法名是否存在 func = getattr(self,cmd_action) #執行對應的方法函數 func(cmd_res) #用戶輸入的[[方法名],[文件名]]傳給方法函數 else: print("\033[31;1m請輸入有效命令\033[0m") def auth(self,cmd): #print(‘auth:‘,cmd) #接受客戶端格式化輸出的 auth 用戶名 密碼 user = self.user_obj.get_user(cmd[1]) #調用Users類中get_user方法,並把cmd[1](用戶名)傳參給get_user方法 print(‘in the ftp_server_auth:‘,user) if user: if user[‘password‘] == cmd[2]: self.current_user = user self.current_path = user["home"] self.user_home = setting.USER_HOME self.conn.send(b"ok") else: self.conn.send(b"Not password") else: self.conn.send(b‘Not username‘) def put(self,cmd): ‘‘‘ 上傳文件函數 :param cmd: 接收用戶輸入的[[方法名],[文件名]] :return: ‘‘‘ #print(‘in the put:‘,cmd) file_name_path = self.user_home + self.current_path +‘\server_home\\‘+ cmd[1] print(‘文件路徑‘,file_name_path) if os.path.isfile(file_name_path): file_totle_size = os.stat(file_name_path).st_size #查看文件大小 self.conn.send(str(file_totle_size).encode()) #將文件大小發送給客戶端 self.conn.recv(1024) #接收客戶端消息 with open(file_name_path,‘rb‘) as f: for line in f: #循環遍歷文件內容 self.conn.send(line) #並將文件內容發送給客戶端 print("send done>>>") else: print(‘\033[31;1m文件不存在\033[0m‘) self.conn.send(‘302‘.encode()) def get(self,cmd): ‘‘‘ 接收客戶端上傳文件函數 :param cmd: :return: ‘‘‘ print(cmd) file_path = self.user_home + self.current_path + ‘\server_home\\‘ + cmd[1] #文件路徑 file_totle_size = cmd[2] #接收客戶端上傳文件大小 file_totle_size = int(file_totle_size) with open(file_path,‘wb‘) as f: self.conn.send(‘300‘.encode()) #返回客戶端參數300 revered_file_size = 0 #初始接收文件大小 while revered_file_size < file_totle_size: #開始接收客戶端上傳文件 if file_totle_size - revered_file_size <= 1024: size = file_totle_size-revered_file_size else: size = 1024 data = self.conn.recv(size) revered_file_size += len(data) f.write(data) else: print("文件接收完畢") def dir(self,cmd): ‘‘‘ 查看服務端目錄文件信息函數 :param cmd: :return: ‘‘‘ print(cmd) file_path = self.user_home + self.current_path + ‘\server_home\\‘ res = os.popen(‘%s %s‘%(cmd[0],file_path)).read() print(‘服務端文件目錄信息:‘,res) if len(res) == 0 : res = ‘cmd has not output‘ self.conn.send(str(len(res)).encode()) #服務端發送目錄文件大小給客戶端 self.conn.recv(1024) #接收客戶端回調信息 "ok" self.conn.send(res.encode()) #服務端發送目錄文件信息給客戶端ftp_server.py
db目錄下的數據文件
[ { "username":"alex", "password":"admin", "home":"\\home\\alex\\", } ]user.db
老男孩Day8作業:FTP