1、用户加密认证 2、允许同时多用户登录 3、每个用户有自己的家目录 ,且只能访问自己的家目录 4、对用户进行磁盘配额,每个用户的可用空间不同 5、允许用户在ftp server上随意切换目录 6、允许用户查看当前目录下文件 7、允许上传和下载文件,保证文件一致性 8、文件传输过程中显示进度条 附加功能:支持文件的断点续传python 3.5 用socketserver实现FTP ConfigParser 是Python自带的模块, 用来读写配置文件,将用户信息以下边的格式存入account.py文件,读出后进行判断
[DEFAULT][alex]Password = 123456Quotation = 100[jack]Password = 123456Quotation = 100
2、允许同时多用户登录 从scokerserver 继承 socketserver.ThreadingTCPServer即可实现
3、每个用户有自己的家目录 ,且只能访问自己的家目录 将所有路径封装在home目录下
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))USER_HOME = '%s\home' % BASE_DIRLOG_DIR = '%s\log' % BASE_DIRLOG_LEVEL = 'DEBUG'
4、允许用户在ftp server上随意切换目录 用os模块改变工作目录
os.chdir(func_val)
5、允许用户查看当前目录下文件 用os模块的os.listdir,下为server端代码
def _ls(self,*args,**kwargs):'''显示当前目录下的所有文件'''if os.getcwd() == '%s\\bin'% settings.BASE_DIR: user_home_dir = "%s\%s" % (settings.USER_HOME, self.user["Username"]) self.request.send(json.dumps(os.listdir(user_home_dir)).encode())else:self.request.send(json.dumps(os.listdir()).encode())
6、允许上传和下载文件,保证文件一致性 判断上传和下载的文件在传输前后的大小,用以判断文件是否保持一致
1 #server端 2 # 3 def _put(self,*args,**kwargs): 4 '''上传文件命令''' 5 data = args[0] 6 7 response = self.get_response() 8 if response["status_code"] == 257: # ready to receive 9 self.request.send(b'1') # send confirmation to server 10 user_home_dir = "%s\%s" % (settings.USER_HOME, self.user["Username"]) 11 base_filename = "%s\%s" % (user_home_dir, data.get('filename')) 12 received_size = 0 13 file_obj = open(base_filename, 'wb') 14 if data.get('md5'): 15 md5_obj = hashlib.md5() 16 while received_size < response['<mark style="color:transparent">本文来源gaodaimacom搞#^代%!码网@</mark>file_size']: 17 line = self.request.recv(4096) 18 received_size += len(line) 19 file_obj.write(line) 20 md5_obj.update(line) 21 else: 22 file_obj.close() 23 md5_val = md5_obj.hexdigest() 24 self.send_response(258, {'md5': md5_val}) 25 print("-----file rece done-----") 26 27 else: 28 while received_size < response['file_size']: 29 data = self.request.recv(4096) 30 received_size += len(data) 31 file_obj.write(data) 32 else: 33 print("-----file rece done-----") 34 file_obj.close() 35 else: 36 print(STATUS_CODE[response["status_code"]]) 37 38 39 def _get(self,*args,**kwargs): 40 '''下载文件命令''' 41 data = args[0] 42 if data.get('filename') is None: 43 self.send_response(255) 44 user_home_dir = "%s\%s" %(settings.USER_HOME,self.user["Username"]) 45 file_abs_path = "%s\%s" %(user_home_dir,data.get('filename')) 46 print("file abs path",file_abs_path) 47 48 if os.path.isfile(file_abs_path): 49 file_obj = open(file_abs_path,'rb') 50 file_size = os.path.getsize(file_abs_path) 51 self.send_response(257,data = {'file_size':file_size}) 52 self.request.recv(1) #等待客户端确认,防粘包 53 54 if data.get('md5'): 55 md5_obj = hashlib.md5() 56 for line in file_obj: 57 self.request.send(line) 58 md5_obj.update(line) 59 else: 60 file_obj.close() 61 md5_val = md5_obj.hexdigest() 62 self.send_response(258,{'md5':md5_val}) 63 print("send file done...") 64 else: 65 for line in file_obj: 66 self.request.send(line) 67 else: 68 file_obj.close() 69 print("send file done...") 70 else: 71 self.send_response(256) 72 73 74 75 76 # client端 77 # 78 def _get(self,cmd_list): 79 '''下载文件''' 80 print("get--",cmd_list) 81 if len(cmd_list) == 1: 82 print("no filename follows...") 83 return 84 data_header = { 85 'action':'get', 86 'filename':cmd_list[1] 87 } 88 if self.__md5_required(cmd_list): 89 data_header['md5'] = True 90 91 self.sock.send(json.dumps(data_header).encode()) 92 response = self.get_response() 93 print(response) 94 try: 95 if response["status_code"] == 257:#ready to receive 96 self.sock.send(b'1') #send confirmation to server 97 base_filename = cmd_list[1].split('/')[-1] 98 received_size = 0 99 file_obj = open(base_filename,'wb')100 if self.__md5_required(cmd_list):101 md5_obj = hashlib.md5()102 progress = self.show_progress(response['file_size']) #generator103 progress.__next__()104 while received_size < response['file_size']:105 data = self.sock.recv(4096)106 received_size += len(data)107 try:108 progress.send(len(data))109 except StopIteration as e:110 print("100%")111 file_obj.write(data)112 md5_obj.update(data)113 else:114 print("-----file rece done-----")115 file_obj.close()116 md5_val = md5_obj.hexdigest()117 md5_from_server = self.get_response()118 if md5_from_server['status_code'] == 258:119 if md5_from_server['md5'] == md5_val:120 print("%s 文件一致性校验成功!"% base_filename)121 print(md5_val,md5_from_server)122 123 else:124 progress = self.show_progress(response['file_size']) # generator125 progress.__next__()126 while received_size < response['file_size']:127 data = self.sock.recv(4096)128 received_size += len(data)129 file_obj.write(data)130 try:131 progress.send(len(data))132 except StopIteration as e:133 print("100%")134 else:135 print("-----file rece done-----")136 file_obj.close()137 else:138 print(STATUS_CODE[response["status_code"]])139 except Exception as e:140 base_file_size = os.path.getsize(base_filename)141 with open('data\\breakpoint', 'wb') as br_po:142 data_header['action'] = 'breakpoint'143 data_header['breakpoint'] = base_file_size144 br_po.write(json.dumps(data_header).encode())145 146 147 def _put(self,cmd_list):148 '''上传文件'''149 print("put--", cmd_list)150 if len(cmd_list) == 1:151 print("no filename follows...")152 return153 data_header = {154 'action': 'put',155 'filename': cmd_list[1]156 }157 if self.__md5_required(cmd_list):158 data_header['md5'] = True159 160 self.sock.send(json.dumps(data_header).encode())161 if os.path.isfile(cmd_list[1]):162 file_obj = open(cmd_list[1], 'rb')163 file_size = os.path.getsize(cmd_list[1])164 self.send_response(257, data={'file_size': file_size})165 self.sock.recv(1) # 等待服务器端确认166 if self.__md5_required(cmd_list):167 md5_obj = hashlib.md5()168 progress = self.show_progress(file_size) # generator169 progress.__next__()170 for line in file_obj:171 self.sock.send(line)172 try:173 progress.send(len(line))174 except StopIteration as e:175 print("100%")176 md5_obj.update(line)177 else:178 file_obj.close()179 md5_val = md5_obj.hexdigest()180 md5_from_server = self.get_response()181 if md5_from_server['md5'] == md5_val:182 print("%s 文件一致性校验成功!"% cmd_list[1])183 self.send_response(258, {'md5': md5_val})184 print("send file done...")185 else:186 progress = self.show_progress(file_size) # generator187 progress.__next__()188 for line in file_obj:189 self.sock.send(line)190 try:191 progress.send(len(line))192 except StopIteration as e:193 print("100%")194 else:195 file_obj.close()196 print("send file done...")197 else:198 print(256)
get and put