Python 程序:ftp
1、ftp实现功能
2、目录结构
3、代码
4、效果展示
一、ftp实现功能
1、用户登陆认证
2、多用户同时登陆
3、不同用户家目录不同
4、查看目录下文件
5、用户可以在家目录下切换目录
6、用户可以在家目录下创建目录
7、用户可以在家目录下删除文件或目录
8、用户磁盘配额(不同用户配额可不同,当文件大小超出服务器分配空间大小拒绝上传)
9、上传:支持断点续传
10、下载:支持断点续传和进度条显示
二、目录结构
三、代码
1 import socket,os,json,sys 2 class FtpClient(object): 3 4 def __init__(self,ip,port): 5 self.client = socket.socket() 6 self.client.connect((ip,port)) 7 self.exit_flag = False 8 self.interactive() 9 10 def auth(self): 11 retry_count = 0 12 while retry_count < 3: 13 username = input("username:").strip() 14 if len(username) == 0:continue 15 # passwd = getpass.getpass("password:") #pycharm显示有问题 16 passwd = input("passwd:").strip() 17 msg_dic = { 18 "action":"ftp_auth", 19 "username":username, 20 "passwd":passwd 21 } 22 self.client.send(json.dumps(msg_dic).encode("utf-8")) 23 24 auth_feedback = self.client.recv(1024) 25 auth_feedback = auth_feedback.decode() 26 if auth_feedback == "success": 27 print("\033[32;1m登录成功!\033[0m") 28 self.username = username 29 self.cur_path = username 30 return True 31 else: 32 print ("\033[31;1m账号密码错误!\033[0m") 33 retry_count +=1 34 else: 35 print ("\033[31;1m尝试次数过多,exit!\033[0m") 36 37 def interactive(self): 38 ftp_version = self.client.recv(1024) 39 print(ftp_version.decode()) 40 self.auth() #登录验证 41 self.help() 42 while True: 43 cmd = input(">>:").strip() 44 if len(cmd) == 0: 45 continue 46 cmd_str = cmd.split()[0] #输入的第一个字符永远为指令,取出 47 if hasattr(self,"cmd_%s"%cmd_str): 48 func = getattr(self,"cmd_%s"%cmd_str) 49 func(cmd) 50 else: 51 self.help() 52 53 def cmd_dir(self,*args): 54 cmd_split = args[0].split() 55 filename = ‘ ‘.join(cmd_split[1:]) 56 msg_dic = { 57 "action":cmd_split[0], 58 "filename":filename 59 } 60 self.client.send(json.dumps(msg_dic).encode("utf-8")) 61 # 防止粘包等服务器确认 62 cmd_res_size = self.client.recv(1024) 63 self.client.send(b"ok") 64 cmd_res_size = int(cmd_res_size.decode()) 65 received_size = 0 66 while received_size < cmd_res_size: 67 data = self.client.recv(1024) 68 received_size +=len(data) 69 print(data.decode()) 70 71 def cmd_cd(self,*args): 72 73 cmd_split = args[0].split() 74 filename = ‘ ‘.join(cmd_split[1:]) 75 msg_dic = { 76 "action":cmd_split[0], 77 "filename":filename 78 } 79 self.client.send(json.dumps(msg_dic).encode("utf-8")) 80 feedback = self.client.recv(100) 81 feedback = feedback.decode() 82 if feedback.startswith("switch_dir::ok"): 83 self.cur_path = feedback.split("::")[-1] 84 else: 85 print ("\033[31;1m%s\033[0m" % feedback.split("::")[-1]) 86 87 def cmd_rmdir(self,*args): 88 cmd_split = args[0].split() 89 filename = ‘ ‘.join(cmd_split[1:]) 90 msg_dic = { 91 "action":cmd_split[0], 92 "filename":filename 93 } 94 self.client.send(json.dumps(msg_dic).encode("utf-8")) 95 feedback = self.client.recv(100) 96 print(feedback.decode()) 97 98 def cmd_mkdir(self,*args): #只支持创建目录,创建文件自己上传就行 99 cmd_split = args[0].split() 100 filename = ‘ ‘.join(cmd_split[1:]) 101 msg_dic = { 102 "action":cmd_split[0], 103 "filename":filename 104 } 105 self.client.send(json.dumps(msg_dic).encode("utf-8")) 106 feedback = self.client.recv(100) 107 print(feedback.decode()) 108 109 def cmd_put(self,*args): 110 cmd_split = args[0].split() 111 if len(cmd_split) > 1: 112 filename = cmd_split[1] 113 if os.path.isfile(filename): 114 filesize = os.stat(filename).st_size 115 # msg_str = "%s|%s"%(filename,filesize) 116 msg_dic = { 117 "action":cmd_split[0], 118 "filename":filename, 119 "size":filesize, 120 "has_file":False 121 } 122 self.client.send(json.dumps(msg_dic).encode("utf-8")) 123 #防止粘包等服务器确认 124 server_response = self.client.recv(1024) #此时服务器端判断大小是否超出磁盘配额,返回参数 125 data = server_response.decode() 126 data_list= data.split("|") 127 if data_list[0] == "ok" and data_list[1] == "no": 128 f = open(filename,"rb") 129 for line in f : 130 self.client.send(line) 131 else: 132 print("file upload success..") 133 f.close() 134 elif data_list[0] == "ok" and data_list[1] != "no": 135 print(data_list[1]) 136 size = int(data_list[1]) 137 f = open(filename,"rb") 138 f.seek(size)#seek到断点位置 139 for line in f : 140 self.client.send(line) 141 else: 142 print("file upload success..") 143 f.close() 144 else: 145 print(server_response.decode()) 146 else: 147 print(filename,"is not exist") 148 149 def cmd_get(self,*args): 150 cmd_split = args[0].split() 151 if len(cmd_split) > 1: 152 filename = cmd_split[1] 153 msg_dic = { 154 "action":cmd_split[0], 155 "filename":filename, 156 "size":0, 157 "overridden":True 158 } 159 160 if os.path.isfile(filename): 161 print("文件已存在") 162 old_size = os.stat(filename).st_size 163 msg_dic["size"] = old_size 164 else: 165 print("文件不存在") 166 old_size = 0 167 msg_dic["size"] = old_size 168 169 self.client.send(json.dumps(msg_dic).encode("utf-8")) 170 #防止粘包等服务器确认 171 data = self.client.recv(1024) 172 server_response = json.loads(data.decode()) 173 174 if server_response["filename"] is not None: 175 file_name = server_response["filename"] 176 if old_size>=server_response["size"]: 177 print("文件已下载完毕!") #文件已下载完毕 178 received_size = old_size 179 else: 180 f = open(filename, ‘ab‘) 181 received_size = old_size 182 self.client.send(b"ok") 183 while received_size < server_response["size"]: 184 if server_response["size"] - received_size >= 1024: #此时要收不只一次 185 size = 1024 186 else: #最后一次收的数据大小,防止多收,避免粘包 187 size = server_response["size"] - received_size 188 data = self.client.recv(1024) 189 received_size += len(data) #每次收到的大小 190 f.write(data) 191 cur_percent = received_size / server_response["size"] * 100 192 self.show_progress(server_response["size"],received_size,cur_percent) #显示进度条 193 print("下载成功!") 194 else: 195 print("文件不存在!") 196 197 def show_progress(self,total,finished,percent): 198 progress_mark = "=" * int(percent/2) 199 sys.stdout.write("[%s/%s]%s>%s\r" %(total,finished,progress_mark,percent)) 200 sys.stdout.flush() 201 if percent == 100: 202 print (‘\n‘) 203 204 def help(self): 205 msg = ‘‘‘ 206 ---命令菜单--- 207 dir 208 mkdir filename 209 rmdir filename 210 cd filename 211 get filename 212 put filename 213 ‘‘‘ 214 print(msg) 215 216 ftp = FtpClient("localhost",9999)
ftp_client
ftp_server
1 accounts = { 2 ‘zz‘: {‘passwd‘: "123", 3 ‘quotation‘: 100000000, 4 ‘home‘: ‘home/zz‘ 5 }, 6 ‘jj‘:{‘passwd‘: "123", 7 ‘quotation‘: 1000000, 8 ‘home‘: ‘home/jj‘ 9 }, 10 }
user_data
四、效果展示
1、用户登陆认证:
2、多用户同时登录
3、不同用户家目录不同
4、查看目录下文件
5、在家目录下切换目录
6、在家目录下任意目录里创建目录
7、删除目录或文件
8、用户磁盘配额
9、上传:支持断点续传
10、下载:支持断点续传和进度条显示
原文地址:https://www.cnblogs.com/hy0822/p/9224571.html
时间: 2024-11-14 10:33:35