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 #
SockeServer 实现

 

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()
client 端

 

 

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')
settings

 

posted @ 2016-07-26 19:40  咖啡茶  阅读(175)  评论(0)    收藏  举报