Python作业--实现文件的续传
开发一个多用户在线的FTP程序
1:用户MD5 加密认证
2:允许同时多用户登陆 sockserver
3:执行名称
ipconfig
subprocess
4:上传文件
文件上传过程中显示进度条
支持文件的断点续传
传递过程中带文件名称
1:服务器端
1 #!/usr/bin/evn python 2 #-*- coding:utf-8 -*- 3 import os 4 import socketserver 5 from config import settings 6 import pickle 7 import hashlib 8 import subprocess 9 import time 10 11 12 class MyServer(socketserver.BaseRequestHandler): 13 def handle(self): 14 while True: 15 conn = self.request # 第一个循环里面和不和用户有交互,仅仅用来监听连接。当用户断开连接后,在有交互的位置会发生异常,因为第一层循环仅仅为了监听有用户连接。 16 Flag = True 17 18 while Flag: #从第二层循环开始进行交互。使用Flag,如果发生异常,表示Flag为Flase,退出循环。不在和此用户交互。 19 try: 20 conn.sendall(bytes('请选择操作 : \n 1:登陆: \n 2: 注册\n 3:退出\n', encoding='utf-8')) 21 option = str(conn.recv(1024),encoding = 'utf-8') 22 if option == '1': 23 is_login = self.login() 24 conn.sendall(bytes(str(is_login), encoding='utf-8')) 25 if is_login: 26 while True: 27 28 conn.sendall(bytes('请选择操作:\n 1:执行名称:\n 2: FTP上传文件\n 3:返回上一层\n', encoding='utf-8')) 29 option3 = str(conn.recv(1024), encoding='utf-8') 30 if option3 == '1': 31 print(option3) 32 ex_result = self.my_exec() 33 print(option3) 34 conn.sendall(bytes(ex_result, encoding='utf-8')) 35 36 elif option3 == '2': 37 self.file_ftp() 38 39 elif option3 == '3': 40 break 41 else: 42 conn.sendall(bytes('输入错误\n', encoding='utf-8')) 43 44 #conn.recv(1024) 45 46 elif option == '2': 47 isregistr = self.register() 48 conn.sendall(bytes(str(isregistr), encoding='utf-8')) 49 elif option == '3': 50 break 51 else: 52 conn.sendall(bytes('输入错误!', encoding='utf-8')) 53 except Exception as e: 54 Flag = False 55 break 56 57 58 59 60 61 def register(self): 62 user_list = [] 63 conn = self.request 64 conn.sendall(bytes('请输入用户名和密码:',encoding = 'utf-8')) 65 user = str(conn.recv(1024),encoding = 'utf-8') 66 conn.sendall(bytes('ok',encoding = 'utf-8')) 67 pwd = str(conn.recv(1024),encoding = 'utf-8') 68 69 hash = hashlib.md5(bytes('keys123', encoding='utf-8')) 70 hash.update(bytes(pwd, encoding='utf-8')) 71 pwd_md5 = hash.hexdigest() 72 73 user_list.append({'user': user, 'pwd': pwd_md5}) 74 75 if os.path.exists(settings.user_dir): 76 f1 = open(settings.user_dir, 'rb') 77 user_list = pickle.load(f1) 78 f1.close() 79 for item in user_list: 80 if item['user'] == user: 81 return False 82 user_list.append({'user':user,'pwd':pwd_md5}) 83 pickle.dump(user_list,open(settings.user_dir,'wb')) 84 return True 85 86 87 def login(self): 88 conn = self.request 89 conn.sendall(bytes('请输入用户名和密码:', encoding='utf-8')) 90 user = str(conn.recv(1024), encoding='utf-8') 91 conn.sendall(bytes('ok', encoding='utf-8')) 92 pwd = str(conn.recv(1024), encoding='utf-8') 93 94 hash = hashlib.md5(bytes('keys123', encoding='utf-8')) 95 hash.update(bytes(pwd, encoding='utf-8')) 96 pwd_md5 = hash.hexdigest() 97 98 user_list = pickle.load(open(settings.user_dir, 'rb')) 99 100 print('登陆用户名称和密码:',user, pwd_md5) 101 for item in user_list: 102 print(item['user'],item['pwd']) 103 if item['user'] == user and item['pwd'] == pwd_md5 : 104 return True 105 else: 106 return False 107 108 109 def my_exec(self): 110 conn = self.request 111 conn.sendall(bytes('输入命令:\n', encoding='utf-8')) 112 ex = str(conn.recv(1024), encoding='utf-8') 113 print(ex) 114 obj = subprocess.Popen(ex, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True,shell = True) 115 obj.stdin.write("print(1)\n") 116 obj.stdin.write("print(2)") 117 obj.stdin.close() 118 cmd_out = obj.stdout.read() 119 print(type(cmd_out)) 120 obj.stdout.close() 121 cmd_error = obj.stderr.read() 122 obj.stderr.close() 123 124 #cmd_out = '测试下' 125 126 if len(cmd_out)>0: 127 return cmd_out 128 else: 129 return cmd_error 130 131 132 def file_ftp(self): 133 conn = self.request 134 conn.sendall(bytes('请输入文件名称 ', encoding='utf-8')) 135 file_name = str(conn.recv(1024),encoding = 'utf-8') 136 conn.sendall(bytes('ok ', encoding='utf-8')) #解决粘豆包问题 137 total_size = str(conn.recv(1024),encoding = 'utf-8') 138 139 num = 0 140 size = 0 141 # new_file = os.path.join(settings.file_base_dir, str(time.time())+file_name) 142 new_file = os.path.join(settings.file_base_dir, 'new' + file_name) 143 print(new_file) 144 if os.path.exists(new_file): 145 size = os.stat(new_file).st_size 146 print('文件大小 ',size) 147 if size == total_size: 148 conn.sendall(bytes('1ok',encoding = 'utf-8')) 149 else: 150 num = size 151 conn.sendall(bytes(str(size),encoding = 'utf-8')) 152 f2 = open(new_file, 'ab') 153 print('续传') 154 #f2.seek(size) 155 while True: 156 print(num,total_size) 157 if num == int(total_size): 158 break 159 else: 160 data = conn.recv(1024) 161 num += len(data) 162 f2.write(data) 163 164 else: 165 print('从头传') 166 conn.sendall(bytes('2ok', encoding='utf-8')) 167 f2 = open(new_file, 'wb') 168 while True: 169 #print(num,total_size) 170 if num == int(total_size): 171 break 172 else: 173 data = conn.recv(1024) 174 num += len(data) 175 f2.write(data) 176 177 178 f2.close() 179 180 181 182 if __name__ == '__main__': 183 server = socketserver.ThreadingTCPServer(('127.0.0.1',8999),MyServer ) 184 server.serve_forever() 185 186 #
2:客户端
1 #!/usr/bin/evn python 2 #-*- coding:utf-8 -*- 3 import socket 4 import os 5 from config import settings 6 import sys 7 import time 8 9 ip_port = ('127.0.0.1',8999) 10 sk = socket.socket() 11 sk.connect(ip_port) #连接到sever端 12 while True: 13 #收到server 发送的回复 14 server_replay = str(sk.recv(1024), encoding='utf-8') 15 print('aaa',server_replay) 16 option1= input('>>>') 17 sk.sendall(bytes(option1,encoding = 'utf-8') )#发送请求 18 19 if option1 == '1': 20 server_replay = str(sk.recv(1024), encoding='utf-8') 21 print(server_replay) 22 user = input('用户名:') 23 sk.sendall(bytes(user, encoding='utf-8')) # 发送请求 24 sk.recv(1024) 25 pwd = input('密码:') 26 sk.sendall(bytes(pwd, encoding='utf-8')) # 发送请求 27 28 login_replay = str(sk.recv(1024), encoding='utf-8') 29 if login_replay == 'True': 30 print('登陆成功') 31 while True: 32 secserver_replay = str(sk.recv(1024), encoding='utf-8') #接受二级菜单 33 print(secserver_replay) 34 inp2 = input('>>>') 35 sk.sendall(bytes(inp2, encoding='utf-8')) # 发送请求 36 if inp2 == '1': #选择为1 执行命令 37 secserver_replay = str(sk.recv(1024), encoding='utf-8') #接受用户发送的消息 38 print(secserver_replay) 39 ex = input('>>>') 40 sk.sendall(bytes(ex, encoding='utf-8')) # 发送需要执行的命令 41 ex_replay = str(sk.recv(1024), encoding='utf-8') 42 print(ex_replay) 43 if inp2 == '2': #选择2为上传FTP文件 44 file_replay = str(sk.recv(1024), encoding='utf-8') 45 print(file_replay) 46 file_name = input('>>>') 47 file_path = os.path.join(settings.file_base_dir,file_name) 48 if os.path.exists(file_path): 49 total_size = os.stat(file_path).st_size 50 51 sk.sendall(bytes(file_name, encoding='utf-8')) # 发送需要执行的名称 52 sk.recv(1024) 53 54 total_size = os.stat(file_path).st_size 55 sk.sendall(bytes(str(total_size), encoding='utf-8')) # 发送文件 56 57 58 #开始发送文件,如果文件已经存在,但是小于当前文件,则认为断点续传,等于则认为已经存在,不续传。否则重新传。 59 r = str(sk.recv(1024),encoding = 'utf-8') 60 if r == '1ok': 61 print('文件已经存在') 62 else: 63 if r == '2ok': 64 position =0 65 else: 66 position = int(r) 67 68 with open(file_path, 'rb') as f1: 69 f1.seek(position) 70 for line in f1: 71 #print(line) 72 sk.sendall(line) # 发送文件 73 position += len(line) 74 percent = float(position) / total_size 75 print('发送 %s %% %s'%(percent*100,int(percent*100)*'*')) 76 print('发送完成!') 77 78 else: 79 print('文件不存在') 80 81 if inp2 == '3': #选择3返回上层目录 82 break 83 #sk.sendall(bytes('ok', encoding='utf-8')) # 在下一循环前,发送ok,解决粘豆包问题 84 85 86 87 else: 88 print('请检查用户名和密码') 89 90 if option1 == '2': 91 server_replay = str(sk.recv(1024), encoding='utf-8') 92 print(server_replay) 93 user = input('用户名:') 94 sk.sendall(bytes(user, encoding='utf-8')) # 发送请求 95 sk.recv(1024) 96 pwd = input('密码:') 97 sk.sendall(bytes(pwd, encoding='utf-8')) # 发送请求 98 register_replay = str(sk.recv(1024), encoding='utf-8') 99 if register_replay == 'True': 100 print('注册成功') 101 else: 102 print('用户已经存在') 103 if option1 == '3': 104 break 105 106 107 sk.close()
3:设置
1 #!/usr/bin/evn python 2 #-*- coding:utf-8 -*- 3 4 import os 5 6 Base_Dir = os.path.dirname(os.path.dirname(__file__)) 7 user_dir = os.path.join(Base_Dir,'db','user') 8 9 10 file_base_dir = os.path.join(Base_Dir,'rec')

浙公网安备 33010602011771号