Python 程序:ftp
Posted 水无
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python 程序:ftp相关的知识,希望对你有一定的参考价值。
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)
1 import socketserver,json,os 2 import user_data 3 from os.path import join, getsize 4 5 class MyTCPHandler(socketserver.BaseRequestHandler): 6 def ftp_auth(self,*args): 7 print (\'----auth----\') 8 auth_res = False 9 cmd_dic = args[0] 10 if len(cmd_dic) == 3: 11 msg_type = cmd_dic["action"] 12 username = cmd_dic["username"] 13 passwd = cmd_dic["passwd"] 14 if username in user_data.accounts: 15 if user_data.accounts[username][\'passwd\'] == passwd: 16 auth_res = True 17 self.login_user = username 18 self.cur_path = \'%s/%s\' %(os.path.dirname(__file__),user_data.accounts[username][\'home\']) 19 self.home_path = \'%s/%s\' %(os.path.dirname(__file__),user_data.accounts[username][\'home\']) 20 self.quotation = user_data.accounts[username][\'quotation\'] 21 else: 22 print (\'---wrong passwd---\') 23 auth_res = False 24 else: 25 auth_res = False 26 else: 27 auth_res = False 28 if auth_res: 29 msg = "success" 30 print (\'\\033[32;1muser:%s has passed authentication!\\033[0m\' %username) 31 else: 32 msg = "fail" 33 self.request.send(msg.encode()) 34 35 def disk_size(self,dir): 36 home_size = 0 37 for root, dirs, files in os.walk(dir): 38 home_size += sum([getsize(join(root, name)) for name in files]) 39 size = self.quotation - home_size 40 return size 41 42 def put(self,*args): 43 \'\'\'接受客户端文件\'\'\' 44 cmd_dic = args[0] 45 filename = cmd_dic["filename"] 46 filesize = cmd_dic["size"] 47 size = self.disk_size(self.home_path) 48 print(size,filesize) 49 if size > int(filesize): 50 if os.path.isfile(filename): 51 print("文件已存在") 52 old_size = os.stat(filename).st_size 53 print(old_size,filesize) 54 if old_size>=filesize: 55 self.request.send(b"ok|no") 56 f = open(filename + "_new","wb") #文件已上传完毕,上传新的文件 57 received_size = 0 58 else: 59 b = "ok|%s"%old_size 60 self.request.send(b.encode()) 61 f = open(filename, \'ab\') 62 received_size = old_size 63 else: 64 self.request.send(b"ok|no") 65 f = open(filename,"wb") 66 received_size = 0 67 68 while received_size < filesize: 69 data = self.request.recv(1024) 70 f.write(data) 71 received_size += len(data) 72 else: 73 print("file [%s] has uploaded.."%filename) 74 75 76 77 78 else: 79 result = "磁盘空间不足!" 80 print(result) 81 self.request.send(result.encode()) 82 83 def get(self,*args): 84 \'\'\'客户端下载文件\'\'\' 85 cmd_dic = args[0] 86 filename = cmd_dic["filename"] 87 get_size = cmd_dic["size"] 88 89 if os.path.isfile(filename): #判断是否已经存在 90 filesize = os.stat(filename).st_size 91 cmd_dic["size"] = filesize 92 self.request.send(json.dumps(cmd_dic).encode("utf-8")) 93 self.request.recv(1024) 94 f = open(filename,"rb") 95 f.seek(get_size)#seek到断点位置 96 for line in f: 97 self.request.send(line) 98 f.close() 99 100 else: 101 cmd_dic[\'filename\'] = None 102 self.request.send(json.dumps(cmd_dic).encode("utf-8")) 103 104 def dir(self,*args): 以上是关于Python 程序:ftp的主要内容,如果未能解决你的问题,请参考以下文章我在哪里更改此 Python 代码片段以将临时文件保存在 tmp 文件夹中?
Python练习册 第 0013 题: 用 Python 写一个爬图片的程序,爬 这个链接里的日本妹子图片 :-),(http://tieba.baidu.com/p/2166231880)(代码片段