FTP
总则:
- 将所有功能都拆分开,写成不同模块,便于管理
- 收发消息要有一个统一的格式,这里为字典形式分为{action, msg}
- 不要用if判断来调用各个功能,用反射,可以减少代码量并且更美观,后期加功能也更方便
- cd指令不要使用改变工作路径的方式,否则无法多用户同时使用
- 文件不要一次全部加载到内存中,而是读一部分传一部分
- 使用状态码来收发执行情况(存于Setting中)
-
服务端
目录
代码
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 import os, sys 2 import socketserver 3 PATH = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) 4 sys.path.append(PATH) 5 6 from core import Start 7 8 if __name__ == '__main__': 9 s = socketserver.ThreadingTCPServer(Start.ip_port, Start.MyServer) 10 s.serve_forever()
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 import os 2 PATH = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) 3 4 buffer_size = 4096 5 ip_port = ('222.195.137.208', 8000) 6 7 STATUS_CODE = { 8 '201': 'Passed authentication.' 9 }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 import re 2 import os 3 import struct 4 from core import Transmission 5 from core import File_sys 6 from config import Setting 7 8 class Cmd: 9 10 11 def __init__(self, data, name, conn, mainpath): 12 self.conn = conn 13 self.data = data 14 self.username = name 15 self.mainpath = mainpath 16 self.buffer_size = Setting.buffer_size 17 18 19 def exit(self): 20 pass 21 22 23 def ls(self): 24 try: 25 file = self.data.split(' ') 26 27 if len(file) == 1: 28 res = os.listdir(self.mainpath) 29 elif len(file) == 2: 30 res = os.listdir(os.path.join(self.mainpath, file[1])) 31 32 reply = '\n'.join(res).encode('utf8') 33 34 self.conn.sendall(struct.pack('i', len(reply))) 35 self.conn.sendall(reply) 36 except Exception as e: 37 reply = str(e).encode('utf8') 38 self.conn.sendall(struct.pack('i', len(reply))) 39 self.conn.sendall(reply) 40 41 42 def cd(self): 43 path_old = self.mainpath 44 recv_path = self.data.split(' ') 45 if len(recv_path) == 2: 46 path = recv_path[1] 47 else: 48 return 49 try: 50 media = re.findall('\.\.', path) 51 if media: 52 count = 0 53 while count < len(media): 54 self.mainpath = os.path.dirname(self.mainpath) 55 count += 1 56 else: 57 self.mainpath = os.path.join(self.mainpath, path) 58 if not re.findall(self.username, self.mainpath): 59 self.mainpath = path_old 60 except Exception: 61 pass 62 63 if not os.path.exists(self.mainpath): 64 return 65 else: 66 return self.mainpath 67 68 69 def rm(self): 70 msg = self.data.split(' ') 71 if len(msg) == 2: 72 file = msg[1] 73 path = os.path.join(self.mainpath, file) 74 if os.path.exists(path): 75 if os.path.isdir(path): 76 try: 77 os.rmdir(path) 78 self.conn.send('1'.encode('utf8')) 79 except Exception: 80 self.conn.send('300'.encode('utf8')) 81 82 elif os.path.isfile(path): 83 try: 84 os.remove(path) 85 self.conn.send('1'.encode('utf8')) 86 except Exception: 87 self.conn.send('300'.encode('utf8')) 88 else: 89 self.conn.send('206'.encode('utf8')) 90 else: 91 self.conn.send('201'.encode('utf8')) 92 93 94 def mkdir(self): 95 try: 96 file = self.data.split(' ')[1] 97 path = os.path.join(self.mainpath, file) 98 os.makedirs(path) 99 except Exception: 100 pass 101 102 103 def down(self): 104 105 try: 106 file = self.data.split(' ')[1] 107 file = os.path.join(self.mainpath, file) 108 file_name = os.path.basename(file) 109 file_path = os.path.dirname(file) 110 111 if os.path.isdir(file): 112 msg = '205' 113 elif file_name not in os.listdir(file_path): 114 msg = '206' 115 else: 116 msg = 'ready' 117 self.conn.send(struct.pack('i', len(msg))) 118 self.conn.sendall(msg.encode('utf8')) 119 120 if msg == 'ready': 121 Transmission.download(self.conn, file) 122 123 except Exception as e: 124 msg = '201' 125 self.conn.send(struct.pack('i', len(msg))) 126 self.conn.sendall(msg.encode('utf8')) 127 128 129 def up(self): 130 131 filename = self.data['filename'] 132 filesize = self.data['filesize'] 133 target_path = self.data['target_path'] 134 135 if target_path: 136 abs_path = os.path.join(self.mainpath, target_path, filename) 137 else: 138 abs_path = os.path.join(self.mainpath, filename) 139 140 File_sys.Logging(abs_path) 141 142 if os.path.exists(os.path.dirname(abs_path)): 143 144 if os.path.exists(abs_path): 145 if os.stat(abs_path).st_size == filesize: 146 self.conn.send('204'.encode('utf8')) 147 else: 148 self.conn.send('801'.encode('utf8')) 149 Transmission.upload_continue(self.conn, filesize, abs_path) 150 151 else: 152 self.conn.send('800'.encode('utf8')) 153 Transmission.upload(self.conn, filesize, abs_path) 154 else: 155 self.conn.send('203'.encode('utf8'))
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 import os 2 import logging 3 from core import Log 4 5 6 def Logging(msg): 7 8 PATH = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), 'logging.log') 9 10 logger = logging.getLogger() 11 12 fh = logging.FileHandler(PATH) 13 sh = logging.StreamHandler() 14 15 fm = logging.Formatter('%(asctime)s %(message)s') 16 17 fh.setFormatter(fm) 18 sh.setFormatter(fm) 19 20 logger.setLevel('INFO') 21 logger.addHandler(fh) 22 logger.addHandler(sh) 23 24 logger.info(msg) 25 26 logger.removeHandler(fh) 27 logger.removeHandler(sh) 28 29 def m_file(name): 30 path = os.listdir() 31 count = 0 32 for file in path: 33 if file != name: 34 count += 1 35 if count == len(path): 36 os.mkdir(name) 37 return name 38 39 def make_home(user_name): 40 home_path = os.path.join(os.getcwd().split('\FTP_server')[0], 'FTP_server') 41 os.chdir(home_path) 42 m_file('home') 43 os.chdir('./home') 44 45 m_file(user_name) 46 os.chdir('./%s' %user_name) 47 48 def get_path(mainpath): 49 path0 = mainpath.split('FTP_server')[1].split(os.sep) 50 path = '/'.join(path0) 51 return path 52 53 def authenticate(conn, addr, buffer_size): 54 while True: 55 56 try: 57 user = conn.recv(buffer_size) 58 user_ = user.decode('utf8').split(',') 59 60 if len(user_) == 3: 61 name = user_[0] 62 passwd = user_[1] 63 Log.log_in(name, passwd) 64 Login_result = True 65 break 66 elif len(user_) == 1: 67 break 68 else: 69 name = user_[0] 70 passwd = user_[1] 71 72 result = Log.log_out(name, passwd) 73 74 if result == '1': 75 log_result = 'Wrong user name' 76 conn.sendall(log_result.encode('utf8')) 77 78 elif result == '2': 79 log_result = 'Wrong password' 80 conn.sendall(log_result.encode('utf8')) 81 else: 82 space = int(result) 83 log_result = 'Ready' 84 conn.sendall(log_result.encode('utf8')) 85 Login_result = True 86 break 87 except Exception as error: 88 break 89 90 space = int(Log.log_out(name, passwd)) 91 92 #Authentication logging 93 msg = '\nLogin successful !!\nUser: %s\tAddr: %s: %s' % (name, addr[0], addr[1]) 94 Logging(msg) 95 96 97 return name, passwd, space, Login_result 98 99 100 101 if __name__ == '__main__': 102 get_file('ssy')
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 import os 2 import struct 3 import socketserver 4 import json 5 6 PATH = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) 7 os.chdir(os.path.join(PATH, 'core')) 8 9 from core import File_sys 10 from core import Command 11 from config import Setting 12 13 14 buffer_size = Setting.buffer_size 15 ip_port = Setting.ip_port 16 17 class MyServer(socketserver.BaseRequestHandler): 18 19 def handle(self): 20 21 Login_result = False 22 23 #login system 24 name, passwd, space, Login_result = File_sys.authenticate(self.request, self.client_address, buffer_size) 25 26 # file system 27 File_sys.make_home(name) 28 self.mainpath = os.path.join(Setting.PATH, 'home', name) 29 30 while Login_result: 31 32 try: 33 #send current path 34 35 path = File_sys.get_path(self.mainpath) 36 path_len = len(path) 37 path_len_struct = struct.pack('i', path_len) 38 39 self.request.recv(1) 40 41 self.request.send(path_len_struct) 42 self.request.sendall(path.encode('utf8')) 43 44 #receive command 45 data_json = self.request.recv(buffer_size).decode('utf8') 46 data = json.loads(data_json) 47 48 #logging 49 log_msg = '\nReceived message:%s' %data 50 File_sys.Logging(log_msg) 51 52 if not data:break 53 54 #run command 55 if len(data) == 1: 56 cmd = data['action'].split(' ')[0] 57 data = data['action'] 58 else: 59 cmd = data['action'] 60 61 c = Command.Cmd(data, name, self.request, self.mainpath) 62 63 if hasattr(c, cmd): 64 func = getattr(c, cmd) 65 res = func() 66 if res: 67 self.mainpath = res 68 69 except Exception as e: 70 File_sys.Logging(e) 71 break 72 73 74 if __name__ == '__main__': 75 76 s = socketserver.ThreadingTCPServer(ip_port, MyServer) 77 s.serve_forever()
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 import os 2 import struct 3 import json 4 import hashlib 5 from config import Setting 6 from core import File_sys 7 8 buffer_size = Setting.buffer_size 9 10 def download(server, file): 11 12 13 14 msg_dic = {} 15 msg_dic['length'] = os.stat(file).st_size 16 msg_dic['name'] = os.path.basename(file) 17 18 file_msg = json.dumps(msg_dic).encode('utf8') 19 20 server.send(struct.pack('i', len(file_msg))) 21 server.sendall(file_msg) 22 f = open(file, 'rb') 23 has_send = 0 24 while has_send < msg_dic['length']: 25 data = f.read(buffer_size) 26 server.sendall(data) 27 has_send += len(data) 28 29 f.close() 30 31 32 def upload(conn, filesize, target_path): 33 34 obj = hashlib.md5() 35 36 has_recv = 0 37 f = open(target_path, 'ab') 38 while has_recv < filesize: 39 file_data = conn.recv(buffer_size) 40 f.write(file_data) 41 #md5校验 42 obj.update(file_data) 43 has_recv += len(file_data) 44 f.close() 45 46 MD5 = obj.hexdigest() 47 MD5_recv = conn.recv(buffer_size).decode('utf8') 48 49 if MD5 == MD5_recv: 50 File_sys.Logging('Upload successed!') 51 conn.send('802'.encode('utf8')) 52 else: 53 File_sys.Logging('Upload failed!') 54 conn.send('803'.encode('utf8')) 55 56 57 def upload_continue(conn, filesize, target_path): 58 59 ans = conn.recv(10).decode('utf8') 60 61 if ans == 'N': 62 upload(conn, filesize, target_path) 63 64 elif ans == 'Y': 65 location = os.stat(target_path).st_size 66 conn.sendall(str(location).encode('utf8')) 67 68 has_recv = 0 69 f = open(target_path, 'ab') 70 while has_recv < filesize-location: 71 file_data = conn.recv(buffer_size) 72 f.write(file_data) 73 has_recv += len(file_data) 74 75 f.close() 76 77 File_sys.Logging('Upload successed!') 78 conn.send('802'.encode('utf8')) 79 80 if __name__ == '__main__': 81 pass
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 import hashlib 2 import configparser 3 import os 4 5 def log_in(user, passwd, space=str(100*1024*1024)): 6 7 #加密 8 my_key = '0822' 9 obj = hashlib.md5(my_key.encode('utf8')) 10 obj.update(passwd.encode('utf8')) 11 12 path = os.path.join(os.getcwd().split(os.sep + 'FTP_server')[0], 'FTP_server', 'user.log') 13 #存储用户信息 14 config = configparser.ConfigParser() 15 config[user] = {} 16 config[user]['passwd'] = obj.hexdigest() 17 config[user]['space'] = space 18 with open(path, 'a') as f: 19 config.write(f) 20 21 def log_out(user, passwd_input): 22 23 my_key = '0822' 24 config = configparser.ConfigParser() 25 path = os.path.join(os.getcwd().split(os.sep + 'FTP_server')[0], 'FTP_server', 'user.log') 26 config.read(path) 27 28 try: 29 user_msg = config.items(user) 30 passwd = user_msg[0][1] 31 obj = hashlib.md5(my_key.encode('utf8')) 32 obj.update(passwd_input.encode('utf8')) 33 34 if obj.hexdigest() == passwd: 35 space = user_msg[1][1] 36 return space 37 else: 38 return '2' 39 40 except Exception as e: 41 return '1' 42 43 44 45 if __name__ == '__main__': 46 # log_in('ssy', '123456') 47 48 user = 'ssy' 49 passwd = '123456' 50 result = log_out(user, passwd)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 import os 2 import logging 3 from core import Log 4 5 6 def Logging(msg): 7 8 PATH = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), 'logging.log') 9 10 logger = logging.getLogger() 11 12 fh = logging.FileHandler(PATH) 13 sh = logging.StreamHandler() 14 15 fm = logging.Formatter('%(asctime)s %(message)s') 16 17 fh.setFormatter(fm) 18 sh.setFormatter(fm) 19 20 logger.setLevel('INFO') 21 logger.addHandler(fh) 22 logger.addHandler(sh) 23 24 logger.info(msg) 25 26 logger.removeHandler(fh) 27 logger.removeHandler(sh) 28 29 def m_file(name): 30 path = os.listdir() 31 count = 0 32 for file in path: 33 if file != name: 34 count += 1 35 if count == len(path): 36 os.mkdir(name) 37 return name 38 39 def make_home(user_name): 40 home_path = os.path.join(os.getcwd().split(os.sep + 'FTP_server')[0], 'FTP_server') 41 os.chdir(home_path) 42 m_file('home') 43 os.chdir('./home') 44 45 m_file(user_name) 46 47 48 def get_path(mainpath): 49 path0 = mainpath.split('FTP_server')[1].split(os.sep) 50 path = '/'.join(path0) 51 return path 52 53 def authenticate(conn, addr, buffer_size): 54 while True: 55 56 # try: 57 user = conn.recv(buffer_size) 58 user_ = user.decode('utf8').split(',') 59 60 if len(user_) == 3: 61 name = user_[0] 62 passwd = user_[1] 63 Log.log_in(name, passwd) 64 Login_result = True 65 break 66 elif len(user_) == 1: 67 break 68 else: 69 name = user_[0] 70 passwd = user_[1] 71 72 result = Log.log_out(name, passwd) 73 74 if result == '1': 75 log_result = 'Wrong user name' 76 conn.sendall(log_result.encode('utf8')) 77 78 elif result == '2': 79 log_result = 'Wrong password' 80 conn.sendall(log_result.encode('utf8')) 81 else: 82 space = int(result) 83 log_result = 'Ready' 84 conn.sendall(log_result.encode('utf8')) 85 Login_result = True 86 break 87 # except Exception as error: 88 # break 89 90 space = int(Log.log_out(name, passwd)) 91 92 #Authentication logging 93 msg = '\nLogin successful !!\nUser: %s\tAddr: %s: %s' % (name, addr[0], addr[1]) 94 Logging(msg) 95 96 97 return name, passwd, space, Login_result 98 99 100 101 102 103 104 if __name__ == '__main__': 105 get_file('ssy')
客户端
目录
代码
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 import os 2 import struct 3 from socket import * 4 import optparse 5 import Log_in 6 import Command 7 import Setting 8 9 class Client: 10 11 def __init__(self): 12 self.result = True 13 self.op = optparse.OptionParser() 14 self.op.add_option('-i', '--IP', dest='ip') 15 self.op.add_option('-p', '--P', dest='port') 16 17 options, args = self.op.parse_args() 18 self.verify_args(options, args) 19 20 self.ip_port = (self.ip, self.port) 21 22 #命令行中后面添加参数部分(python ),用于指定服务器地址,在此程序中暂时无用 23 def verify_args(self, options, args): 24 ip = options.ip 25 port = options.port 26 27 if port and ip: 28 if not 0 < int(port) <65535: 29 exit(Setting.STATUS_CODE['100']) 30 else: 31 self.port = int(port) 32 self.ip = ip 33 Setting.ip_port = (self.ip, self.port) 34 else: 35 self.port = None 36 self.ip = ip 37 38 def connect(self): 39 40 self.buffer_size = Setting.buffer_size 41 if not all(self.ip_port): 42 self.ip_port = Setting.ip_port 43 44 self.client = socket(AF_INET, SOCK_STREAM) 45 self.client.connect(self.ip_port) 46 47 def interaction(self): 48 49 client = self.client 50 51 # login system 52 self.result = Log_in.log(client) 53 os.system('cls') 54 55 while self.result: 56 57 # get current path 58 client.send(b'1') 59 60 path_struct = client.recv(4) 61 path_len = struct.unpack('i', path_struct)[0] 62 63 path0 = b'' 64 while len(path0) < path_len: 65 path0 += client.recv(path_len) 66 path = path0.decode('utf8') 67 68 while True: 69 70 msg = input('[%s]>>' % path).strip() 71 if not msg: continue 72 73 cmd = Command.CMD(client, msg, self) 74 cmd_msg = msg.split(' ')[0] 75 76 if hasattr(cmd, cmd_msg): 77 func = getattr(cmd, cmd_msg) 78 func() 79 if not cmd.Return: 80 break 81 else: 82 continue 83 84 else: 85 print(Setting.STATUS_CODE['101']) 86 continue 87 88 client.close() 89 90 if __name__ == '__main__': 91 92 c = Client() 93 c.connect() 94 c.interaction()
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 import struct 2 import os 3 import json 4 import Transmission 5 import Setting 6 7 8 class CMD: 9 10 def __init__(self, client, msg, Client_self): 11 self.buffer_size = Setting.buffer_size 12 self.client = client 13 self.msg = msg 14 self.Client_self = Client_self 15 16 def exit(self): 17 msg = { 18 'action': self.msg 19 } 20 21 msg_json = json.dumps(msg) 22 self.client.send(msg_json.encode('utf8')) 23 self.Client_self.result = False 24 self.Return = False 25 26 def help(self): 27 help_msg = \ 28 ('ls: Lists the files in the current directory.\n' 29 'cd: Enter the directory.\n' 30 'mkdir: Make file.\n' 31 'rm: Remove file.\n' 32 'down: Download file.\n' 33 'up: Upload file.\n' 34 'exit: Login out.') 35 print("\033[32m%s\033[0m" % help_msg) 36 self.Return = True 37 38 def ls(self): 39 client = self.client 40 buffer_size = self.buffer_size 41 msg = { 42 'action': self.msg 43 } 44 45 msg_json = json.dumps(msg) 46 47 client.send(msg_json.encode('utf8')) 48 length = struct.unpack('i', client.recv(4))[0] 49 data = b'' 50 while len(data) < length: 51 data += client.recv(buffer_size) 52 print(data.decode('utf8')) 53 self.Return = False 54 55 def cd(self): 56 msg = { 57 'action': self.msg 58 } 59 60 msg_json = json.dumps(msg) 61 self.client.send(msg_json.encode('utf8')) 62 self.Return = False 63 64 def mkdir(self): 65 msg = { 66 'action': self.msg 67 } 68 69 msg_json = json.dumps(msg) 70 self.client.send(msg_json.encode('utf8')) 71 self.Return = False 72 73 def rm(self): 74 msg = { 75 'action': self.msg 76 } 77 78 msg_json = json.dumps(msg) 79 self.client.send(msg_json.encode('utf8')) 80 result = self.client.recv(self.buffer_size).decode('utf8') 81 if not result == '1': 82 print(Setting.STATUS_CODE[result]) 83 self.Return = False 84 85 def down(self): 86 msg = { 87 'action': self.msg 88 } 89 90 msg_json = json.dumps(msg) 91 92 self.client.sendall(msg_json.encode('utf8')) 93 try: 94 msg_length = struct.unpack('i', self.client.recv(4))[0] 95 msg = self.client.recv(msg_length).decode('utf8') 96 97 if msg == 'ready': 98 Transmission.download(self.client, self.buffer_size) 99 else: 100 print(Setting.STATUS_CODE[msg]) 101 except Exception as e: 102 print(e) 103 finally: 104 self.Return = False 105 106 def up(self): 107 108 try: 109 cmd_msg = self.msg.split(' ') 110 if len(cmd_msg) == 2: 111 action, local_path= cmd_msg 112 target_path = None 113 elif len(cmd_msg) == 3: 114 action, local_path, target_path = self.msg.split(' ') 115 except Exception: 116 print(Setting.STATUS_CODE['201']) 117 else: 118 try: 119 filename = os.path.basename(local_path) 120 filesize = os.stat(local_path).st_size 121 except Exception: 122 self.Return = True 123 print(Setting.STATUS_CODE['202']) 124 125 else: 126 data = { 127 'action': 'up', 128 'filename': filename, 129 'filesize': filesize, 130 'target_path': target_path 131 } 132 133 data_json = json.dumps(data) 134 self.client.sendall(data_json.encode('utf8')) 135 136 back_msg0 = self.client.recv(self.buffer_size).decode('utf8') 137 back_msg1 = Setting.STATUS_CODE[back_msg0] 138 139 if hasattr(Transmission, back_msg1): 140 func = getattr(Transmission, back_msg1) 141 func(self.client, filesize,local_path) 142 else: 143 print(back_msg1) 144 145 146 147 self.Return = False
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 import Setting 2 3 buffer_size = Setting.buffer_size 4 5 def log(client): 6 7 count = 0 8 while True: 9 10 if count == 2: 11 msg = 'off' 12 client.send(msg.encode('utf8')) 13 return False 14 15 while True: 16 name = input('Please input user name:\n').strip() 17 if name: 18 break 19 while True: 20 passwd = input('Please input passwd:\n').strip() 21 if passwd: 22 break 23 24 msg = ('%s,%s' %(name, passwd)) 25 if count == 1: 26 msg += ',1' 27 28 client.send(msg.encode('utf8')) 29 30 if count == 1: 31 return True 32 33 result = client.recv(buffer_size).decode('utf8') 34 35 if result == 'Ready': 36 return True 37 elif result == 'Wrong user name': 38 print(result) 39 media = input('If you want to register new account?(Y/N):\n') 40 if media == 'Y': 41 count = 1 42 continue 43 else: 44 count = 2 45 elif result == 'Wrong password': 46 print(result)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 import sys 2 3 def bar(count, all): 4 total = 40 5 num = int(total*count/all) + 1 6 num_percent = ' %.1f%%' %(count/all*100) 7 sys.stdout.write('\r' + '[' + '■' * num + ' ' * (total - num) + ']' + num_percent) 8 if count == all: 9 sys.stdout.write('\n') 10 sys.stdout.flush()
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 import os 2 3 PATH = os.path.dirname(os.path.abspath(__file__)) 4 buffer_size = 4096 5 ip_port = ('222.195.137.208', 8000) 6 7 STATUS_CODE = { 8 '100': 'Port must in (0, 65535)', 9 '101': 'Disable instruction, please try again or input help.', 10 11 '201': 'Invalid input format.', 12 '202': 'Local file not found.', 13 '203': 'Target path invalid.', 14 '204': 'The file already exists, so there is no need to upload it again.', 15 '205': 'Can not download directory.', 16 '206': 'This file or directory is not exist.', 17 18 '300': 'Can not remove this directory.', 19 '301': 'Can not remove this file.', 20 21 '800': 'upload', 22 '801': 'upload_continue', 23 '802': 'Upload successed!', 24 '803': 'Upload failed.' 25 }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 import os 2 import json 3 import struct 4 import hashlib 5 import Process_bar 6 import Setting 7 8 buffer_size = Setting.buffer_size 9 10 def m_file(name): 11 path = os.listdir() 12 count = 0 13 for file in path: 14 if file != name: 15 count += 1 16 if count == len(path): 17 os.mkdir(name) 18 return name 19 20 def download(client, buffer_size): 21 22 save_path = m_file('Download') 23 24 head_len_struct = client.recv(4) 25 head_len = struct.unpack('i', head_len_struct)[0] 26 27 head = client.recv(head_len).decode('utf8') 28 file_msg = json.loads(head) 29 30 path = os.path.join(save_path, file_msg['name']) 31 total_len = file_msg['length'] 32 has_recv = 0 33 f = open(path, 'ab') 34 35 while has_recv < total_len: 36 data = client.recv(buffer_size) 37 f.write(data) 38 has_recv += len(data) 39 Process_bar.bar(has_recv, total_len) 40 41 42 43 def upload(client, filesize, local_path): 44 45 obj = hashlib.md5() 46 f = open(local_path, 'rb') 47 has_send = 0 48 49 while has_send < filesize: 50 data_file = f.read(buffer_size) 51 client.sendall(data_file) 52 #md5校验 53 obj.update(data_file) 54 has_send += len(data_file) 55 Process_bar.bar(has_send, filesize) 56 57 f.close() 58 MD5 = obj.hexdigest() 59 client.sendall(MD5.encode('utf8')) 60 61 result = client.recv(Setting.buffer_size).decode('utf8') 62 63 print(Setting.STATUS_CODE[result]) 64 65 66 67 def upload_continue(client, filesize, local_path): 68 69 print('The existing file has not been uploaded, whether to continue?(Y/N)') 70 ans = input() 71 72 if ans in ('Y', 'y'): 73 client.send('Y'.encode('utf8')) 74 print('Continue to upload...') 75 76 location = int(client.recv(buffer_size).decode('utf8')) 77 78 f = open(local_path, 'rb') 79 f.seek(location) 80 has_send = location 81 82 while has_send < filesize: 83 data_file = f.read(Setting.buffer_size) 84 client.sendall(data_file) 85 has_send += len(data_file) 86 Process_bar.bar(has_send, filesize) 87 88 89 f.close() 90 91 result = client.recv(Setting.buffer_size).decode('utf8') 92 print(Setting.STATUS_CODE[result]) 93 94 95 else: 96 print('Upload again...') 97 client.send('N'.encode('utf8')) 98 upload(client, filesize,local_path)
总结:
- 实现的功能可以在Command模块下查看各个函数
- 给用户分配可存储的额度只完成了分配并记录到账户中,剩下未实现(懒,其实很简单,在每次上传之前进行一次剩余容量的判断就行)
- 只在上传实现了md5校验,不包括断点续传(如需要实现可将每次update的值存到本地,续传的时候读取就行)
- 下载未实现断点续传,原理与上传一致就没写了
- 代码还未做提炼,还存在一些代码重复问题