模拟百度云盘版的ftp
Posted 财经知识狂魔
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了模拟百度云盘版的ftp相关的知识,希望对你有一定的参考价值。
思路:
一、分两个大的文件夹,一个是客户端,一个服务端的
二、实现的功能
1. 登陆--对用户名的合法性进行检测(实验账户:alex,123)
注册--设置账户,其中网盘列表设置为空,刚注册的用户给到50下载豆
规则:
用户上传文件是上传到服务端的共享文件库里,同时会添加到自己的网盘里,
上传一个文件就可以奖励50下载豆,并自己上传的文件以后下载不用下载豆
用户去找资源,其实就是把服务端的共享文件库陈列给客户看,客户如果把
服务端的资源文件添加到自己的网盘,必须消耗20下载豆
用户下载不用消耗下载豆,但是只能从自己的网盘里下载
2.进入到FTP客户可以选择:
上传--
遍历自己本地文件库,选择上传,上传过程中显示进度条(支持断点续传)
下载--
遍历自己的网盘,选择下载,下载过程中显示进度条(支持断点下载)
找资源--
遍历服务端的共享文件库,选择添加到自己的网盘
查看我的网盘--
遍历自己的网盘展示
流程图
代码实现
目录:
client端:
client_main.py
import os import sys pat = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) sys.path.append(pat) from config import Config import socket import time import json def main(): #连接服务器 ip_port = (\'127.0.0.1\',8009) sk = socket.socket() sk.connect(ip_port) #接收欢迎信息 bt = sk.recv(1024) print(str(bt,encoding=\'utf-8\')) flag1 = 1 while flag1: # 让客户选择操作 print(\'\\t1\\t登陆\\n\\t2\\t注册\') choose = input(\'请选择序号选择你的操作:\') if choose == \'2\': sk.sendall(bytes(choose,encoding=\'utf-8\')) print(\'注册页面!\') while True: reg_usr = input(\'请输入注册用户名:\') sk.sendall(bytes(reg_usr,encoding=\'utf-8\')) ret = str(sk.recv(1024),encoding=\'utf-8\') if ret == \'合法\': reg_pwd = input(\'请输入注册密码:\') sk.sendall(bytes(reg_pwd,encoding=\'utf-8\')) bt = sk.recv(1024) print(str(bt,encoding=\'utf-8\')) break else: print(ret) elif choose == \'1\': sk.sendall(bytes(choose, encoding=\'utf-8\')) print(\'登陆页面!\') flag2 = 1 while flag2: landed_usr = input(\'请输入用户名:\') sk.sendall(bytes(landed_usr,encoding=\'utf-8\')) ret = str(sk.recv(1024), encoding=\'utf-8\') if ret == \'存在\': while True: landed_pwd = input(\'请输入密码:\') sk.sendall(bytes(landed_pwd,encoding=\'utf-8\')) bt = sk.recv(1024) if str(bt,encoding=\'utf-8\') == \'yes\': print(\'登陆成功!\') flag1 = 0 flag2 = 0 enter_flag = 1 break else: print(str(bt, encoding=\'utf-8\')) else: print(\'用户名不存在!请重新输入!\') else: print(\'输入有误!请重新输入!\') #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ while enter_flag: print(\'\\n\\t1\\t上传\\n\' \'\\t2\\t下载\\n\' \'\\t3\\t找资源\\n\' \'\\t4\\t查看我的网盘\\n\') choose = input(\'请选择你接下来的操作(输入q退出):\') #把客户的选择发过去 sk.sendall(bytes(choose, encoding=\'utf-8\')) if choose == \'1\': #遍历本地文件,并让客户选择 for k,file_name in enumerate(Config.local_file_list,1): print(k,file_name) m = input(\'请选择你要上传的文件:\') file_name = Config.local_file_list[int(m)-1] print(file_name) #把文件名发过去 sk.sendall(bytes(file_name,encoding=\'utf-8\')) print(\'文件名已发过去!\') #接收检测的文件大小 file_size = str(sk.recv(1024),encoding=\'utf-8\') print(\'文件大小已收到!\',file_size) file_name_path = os.path.join(Config.PATH,file_name) all_size = os.stat(file_name_path).st_size print(\'总大小:\',all_size) if all_size != int(file_size): with open(file_name_path,\'rb\') as f: num = int(file_size) f.seek(num) for line in f: sk.sendall(line) file_size = str(sk.recv(1024),encoding=\'utf-8\') sys.stdout.write(\'\\r\') # 每一次清空原行 sys.stdout.write(\'%s%% |%s\' % (int( int(file_size)/ all_size * 100), int(int(file_size) / all_size / 2 * 100) * \'*\')) sys.stdout.flush() # 强制刷新缓冲区 time.sleep(0.3) sk.sendall(bytes(\'1\',encoding=\'utf-8\')) print(\'\\n上传完毕!\') else: print(\'你要上传的文件已存在!\') elif choose == \'2\': s = str(sk.recv(1024), encoding=\'utf-8\') my_wangpan = json.loads(s) print(\'我的网盘:\') for n, file_na in enumerate(my_wangpan, 1): print(n, file_na) load_choose = input(\'请输入序号选择你要下载的文件:\') sk.sendall(bytes(load_choose,encoding=\'utf-8\')) all_size = str(sk.recv(1024),encoding=\'utf-8\') print(type(all_size),all_size) load_file_name = my_wangpan[int(load_choose) - 1] pth = os.path.join(Config.PATH, load_file_name) if load_file_name in Config.local_file_list: file_size = os.stat(pth).st_size if str(file_size) == all_size: sk.sendall(bytes(\'下载过\',encoding=\'utf-8\')) sk.recv(1024) print(\'你本地文件里已有要下载的文件!\') else: print(\'继续下载...\') sk.sendall(bytes(\'下载了一点点\',encoding=\'utf-8\')) sk.recv(1024) sk.sendall(bytes(str(file_size),encoding=\'utf-8\')) with open(pth,\'ab\') as f: while True: bt = sk.recv(1024) if int(file_size / int(all_size)) == 1: break else: f.write(bt) file_size += len(bt) sys.stdout.write(\'\\r\') # 每一次清空原行 sys.stdout.write(\'%s%% |%s\' % (int(file_size / int(all_size) * 100), int(file_size / int(all_size) / 2 * 100) * \'*\')) sys.stdout.flush() # 强制刷新缓冲区 time.sleep(0.3) print(\'\\n下载完成!\') else: print(\'开始下载...\') sk.sendall(bytes(\'没下载\',encoding=\'utf-8\')) sk.recv(1024) file_size = 0 sk.sendall(bytes(\'0\',encoding=\'utf-8\')) with open(pth, \'wb\') as f: while True: bt = sk.recv(1024) if int(file_size / int(all_size)) == 1: break else: f.write(bt) file_size += len(bt) sys.stdout.write(\'\\r\') # 每一次清空原行 sys.stdout.write(\'%s%% |%s\' % (int(file_size / int(all_size) * 100), int(file_size / int(all_size) / 2 * 100) * \'*\')) sys.stdout.flush() # 强制刷新缓冲区 time.sleep(0.3) print(\'下载完成!\') elif choose == \'3\': print(\'进入!\') s = str(sk.recv(1024),encoding=\'utf-8\') print(\'收到json字符\') li = json.loads(s) print(\'资源如下:\') for m,file_name in enumerate(li,1): print(m,file_name) choose = input(\'请选择序号决定你想要添加到网盘的文件(添加一个文件减少20下载豆):\') sk.sendall(bytes(choose,encoding=\'utf-8\')) print(str(sk.recv(1024),encoding=\'utf-8\')) elif choose == \'4\': s = str(sk.recv(1024),encoding=\'utf-8\') my_wangpan = json.loads(s) print(\'我的网盘:\') for n,file_na in enumerate(my_wangpan,1): print(n,file_na) elif choose.lower() == \'q\': exit() else: print(\'你输入有误!请重新输入!\') if __name__ == \'__main__\': main()
config.py
import os import sys pat = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) PATH = os.path.join(pat,\'db\') local_file_list = os.listdir(PATH)
server端
server_main.py
import os import sys pat = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) sys.path.append(pat) from lib import account from config import Config import socketserver import json import time import pickle class MyServer(socketserver.BaseRequestHandler): def handle(self): # print self.request,self.client_address,self.server conn = self.request conn.sendall(bytes(\'欢迎来到百度云盘!\',encoding=\'utf-8\')) flag1 = 1 while flag1: choose = str(conn.recv(1024), encoding=\'utf-8\') if choose == \'2\': while True: reg_usr = str(conn.recv(1024),encoding=\'utf-8\') ret = account.usr_ver(reg_usr) conn.sendall(bytes(ret,encoding=\'utf-8\')) if ret == \'合法\': reg_pwd = str(conn.recv(1024),encoding=\'utf-8\') hash_pwd = account.encrypt(reg_pwd) ob = account.Account() ob.registered(reg_usr,hash_pwd) account.info_add(ob) conn.sendall(bytes(\'注册成功!\',encoding=\'utf-8\')) break elif choose == \'1\': flag2 = 1 while flag2: landed_usr = str(conn.recv(1024),encoding=\'utf-8\') ret = account.land_usr_ver(landed_usr) conn.sendall(bytes(ret,encoding=\'utf-8\')) if ret == \'存在\': while True: landed_pwd = str(conn.recv(1024),encoding=\'utf-8\') obj = account.landed_ver(landed_usr,landed_pwd) if isinstance(obj,account.Account): conn.sendall(bytes(\'yes\', encoding=\'utf-8\')) flag1 = 0 flag2 = 0 break else: conn.sendall(bytes(obj, encoding=\'utf-8\')) ######################################################################################### while True: #接收客户的操作选择 choose = str(conn.recv(1024),encoding=\'utf-8\') if choose == \'1\': #接收客户发来需要上传的文件名 file_name = str(conn.recv(1024),encoding=\'utf-8\') pat = os.path.join(Config.PATH,file_name) #判断上传的文件是否存在 if file_name in Config.shared_file_list: file_size = os.stat(pat).st_size #对存在的文件,检测大小,把值传过去 conn.sendall(bytes(str(file_size),encoding=\'utf-8\')) with open(pat,\'ab\') as f: flag = 1 while flag: bt = conn.recv(1024) if len(bt) == 1 and bt == bytes(\'1\',encoding=\'utf-8\'): flag = 0 else: f.write(bt) file_size += len(bt) conn.sendall(bytes(str(file_size), encoding=\'utf-8\')) obj.netdisc.append(file_name) obj.download_beans += 50 else: conn.sendall(bytes(\'0\',encoding=\'utf-8\')) file_size = 0 with open(pat,\'wb\') as f: flag = 1 while flag: bt = conn.recv(1024) if len(bt) == 1 and bt == bytes(\'1\', encoding=\'utf-8\'): flag = 0 else: f.write(bt) file_size += len(bt) conn.sendall(bytes(str(file_size), encoding=\'utf-8\')) obj.netdisc.append(file_name) obj.download_beans += 50 elif choose == \'2\': s = json.dumps(obj.netdisc) conn.sendall(bytes(s, encoding=\'utf-8\')) load_choose = str(conn.recv(1024),encoding=\'utf-8\') index_num = int(load_choose) - 1 download_file_name = obj.netdisc[index_num] pat = os.path.join(Config.PATH,download_file_name) all_size = os.stat(pat).st_size print(type(all_size),all_size) conn.sendall(bytes(str(all_size),encoding=\'utf-8\')) if str(conn.recv(1024),encoding=\'utf-8\') != \'下载过\': conn.sendall(bytes(\'知道\',encoding=\'utf-8\')) seek_num = int(str(conn.recv(1024),encoding=\'utf-8\')) with open(pat,\'rb\') as f: f.seek(seek_num) for line in f: conn.sendall(line) time.sleep(3) conn.sendall(bytes(\'0\',encoding=\'utf-8\')) else: conn.sendall(bytes(\'知道\', encoding=\'utf-8\')) elif choose == \'3\': print(\'进入!\') s = json.dumps(Config.shared_file_list) conn.sendall(bytes(s,encoding=\'utf-8\')) print(\'已发出json格式信息\') #收到客户选择信息 choose = str(conn.recv(1024),encoding=\'utf-8\') index_num = int(choose) - 1 index_file_name = Config.shared_file_list[index_num] print(index_file_name) if obj.download_beans >= 20: obj.netdisc.append(index_file_name) obj.download_beans -= 20 conn.sendall(bytes(\'添加成功\',encoding=\'utf-8\')) else: conn.sendall(bytes(\'下载豆不足!添加失败!\',encoding=\'utf-8\')) elif choose.lower() == \'q\': with open(Config.ACCOUNT_INFO_PATH,\'rb\') as f: li = pickle.loads(f.read()) lis = [] for i in li: if i.username == obj.username: lis.append(obj) else: lis.append(i) with open(Config.ACCOUNT_INFO_PATH,\'wb\') as f: f.write(pickle.dumps(lis)) elif choose == \'4\': s = json.dumps(obj.netdisc) conn.sendall(bytes(s,encoding=\'utf-8\')) if __name__ == \'__main__\': server = socketserver.ThreadingTCPServer((\'127.0.0.1\',8009),MyServer) server.serve_forever()
config.py
import os import sys pat = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) sys.path.append(pat) ACCOUNT_INFO_PATH = os.path.join(pat,\'db\',\'用户信息.log\') PATH = os.path.join(pat,\'db\',\'共享文件\') shared_file_list = os.listdir(PATH)
account.py
import os import sys pat = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) sys.path.append(pat) from config import Config import pickle import hashlib class Account: def __init__(self): self.username = None self.password = None self.download_beans = 0 self.netdisc = [] def registered(self,usr,pwd): self.username = usr self.password = pwd self.download_beans = 50 def usr_ver(usr): \'\'\' 注册时验证用户名存不存在 :param usr: 需要验证用户名 :return: 存在--返回用户名已存在,不存在--返回合法 \'\'\' if os.path.exists(Config.ACCOUNT_INFO_PATH): with open(Config.ACCOUNT_INFO_PATH,\'rb\') as f: li = pickle.load(f) for i in li: if i.username == usr: return \'用户名已存在!请重新输入!\' return \'合法\' else: return \'合法\' def encrypt(pwd): \'\'\' 給密码加密的 :param pwd: 需要加密的密码 :return: 返回加密后的哈西值 \'\'\' m = hashlib.md5(bytes(\'明天更美好\',encoding=\'utf-8\')) m.update(bytes(pwd,encoding=\'utf-8\')) return m.digest() def info_add(obj): \'\'\' 把注册好信息写入文件 :param obj: 注册的账户对象 :return: \'\'\' if os.path.exists(Config.ACCOUNT_INFO_PATH): with open(Config.ACCOUNT_INFO_PATH,\'rb\') as f: li = pickle.load(f) li.append(obj) else: li = [] li.append(obj) with open(Config.ACCOUNT_INFO_PATH, \'wb\') as f: pickle.dump(li,f) def land_usr_ver(usr): \'\'\' 登录时验证用户名存不存在 :param usr: 需要验证用户名 :return: 存在--返回存在,不存在--返回你输入的用户名不存在 \'\'\' if os.path.exists(Config.ACCOUNT_INFO_PATH): with open(Config.ACCOUNT_INFO_PATH,\'rb\') as f: li = pickle.load(f) for i in li: if i.username == usr: return \'存在\' return \'输入的用户名不存在!请重新输入!\' else: return \'输入的用户名不存在!请重新输入!\' def landed_ver(usr,pwd2): \'\'\' 用于用户名和密码验证 :param usr: 验证用户名 :param pwd: 验证密码 :return: \'\'\' pwd = encrypt(pwd2) li = pickle.load(open(Config.ACCOUNT_INFO_PATH,\'rb\')) for i in li: if i.username == usr and i.password == pwd: return i return \'密码错误!请重新输入!\'
绝版FTP:猛戳这里
以上是关于模拟百度云盘版的ftp的主要内容,如果未能解决你的问题,请参考以下文章
PyQt5学习记录---监听鼠标拖拽事件实现Mac上百度云盘拖拽效果