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)
ftp_client
  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 程序:ftp

我在哪里更改此 Python 代码片段以将临时文件保存在 tmp 文件夹中?

Python练习册 第 0013 题: 用 Python 写一个爬图片的程序,爬 这个链接里的日本妹子图片 :-),(http://tieba.baidu.com/p/2166231880)(代码片段

python实现FTP程序

一句python代码搭建FTP服务

python-FTP程序