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)
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、下载:支持断点续传和进度条显示

猜你喜欢

转载自www.cnblogs.com/hy0822/p/9224571.html
今日推荐