├── ftp_client ├── bin │ ├── __init__.py │ └── client.py ├── log │ └── __init__.py ├── conf │ └── __init__.py ├── core │ ├── __init__.py │ ├── __pycache__ │ │ ├── main.cpython-36.pyc │ │ ├── __init__.cpython-36.pyc │ │ ├── protocol.cpython-36.pyc │ │ └── ftp_client.cpython-36.pyc │ ├── main.py │ ├── protocol.py │ └── ftp_client.py └── README ├── ftp_server ├── bin │ ├── __init__.py │ └── server.py ├── conf │ └── __init__.py ├── core │ ├── __init__.py │ ├── __pycache__ │ │ ├── main.cpython-36.pyc │ │ ├── update.cpython-36.pyc │ │ ├── __init__.cpython-36.pyc │ │ ├── protocol.cpython-36.pyc │ │ └── ftp_server.cpython-36.pyc │ ├── update.py │ ├── main.py │ ├── protocol.py │ └── ftp_server.py ├── log │ └── __init__.py ├── data │ └── Obser │ │ └── user_info └── README └── README /ftp_client/bin/__init__.py: -------------------------------------------------------------------------------- 1 | # @Time : 2017/10/4 下午12:30 2 | # @Author : user_info -------------------------------------------------------------------------------- /ftp_client/log/__init__.py: -------------------------------------------------------------------------------- 1 | # @Time : 2017/10/4 下午12:31 2 | # @Author : user_info -------------------------------------------------------------------------------- /ftp_server/bin/__init__.py: -------------------------------------------------------------------------------- 1 | # @Time : 2017/10/2 下午4:37 2 | # @Author : user_info -------------------------------------------------------------------------------- /ftp_server/conf/__init__.py: -------------------------------------------------------------------------------- 1 | # @Time : 2017/10/2 下午4:37 2 | # @Author : user_info -------------------------------------------------------------------------------- /ftp_server/core/__init__.py: -------------------------------------------------------------------------------- 1 | # @Time : 2017/10/2 下午4:37 2 | # @Author : user_info -------------------------------------------------------------------------------- /ftp_server/log/__init__.py: -------------------------------------------------------------------------------- 1 | # @Time : 2017/10/2 下午4:37 2 | # @Author : user_info -------------------------------------------------------------------------------- /ftp_client/conf/__init__.py: -------------------------------------------------------------------------------- 1 | # @Time : 2017/10/4 下午12:30 2 | # @Author : user_info -------------------------------------------------------------------------------- /ftp_client/core/__init__.py: -------------------------------------------------------------------------------- 1 | # @Time : 2017/10/4 下午12:30 2 | # @Author : user_info -------------------------------------------------------------------------------- /ftp_server/data/Obser/user_info: -------------------------------------------------------------------------------- 1 | {"account": "Obser", "password": "123", "total": 209715200, "available": 209715200} -------------------------------------------------------------------------------- /ftp_client/core/__pycache__/main.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Obsir/FTP/HEAD/ftp_client/core/__pycache__/main.cpython-36.pyc -------------------------------------------------------------------------------- /ftp_server/core/__pycache__/main.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Obsir/FTP/HEAD/ftp_server/core/__pycache__/main.cpython-36.pyc -------------------------------------------------------------------------------- /ftp_server/core/__pycache__/update.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Obsir/FTP/HEAD/ftp_server/core/__pycache__/update.cpython-36.pyc -------------------------------------------------------------------------------- /ftp_client/core/__pycache__/__init__.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Obsir/FTP/HEAD/ftp_client/core/__pycache__/__init__.cpython-36.pyc -------------------------------------------------------------------------------- /ftp_client/core/__pycache__/protocol.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Obsir/FTP/HEAD/ftp_client/core/__pycache__/protocol.cpython-36.pyc -------------------------------------------------------------------------------- /ftp_server/core/__pycache__/__init__.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Obsir/FTP/HEAD/ftp_server/core/__pycache__/__init__.cpython-36.pyc -------------------------------------------------------------------------------- /ftp_server/core/__pycache__/protocol.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Obsir/FTP/HEAD/ftp_server/core/__pycache__/protocol.cpython-36.pyc -------------------------------------------------------------------------------- /ftp_client/core/__pycache__/ftp_client.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Obsir/FTP/HEAD/ftp_client/core/__pycache__/ftp_client.cpython-36.pyc -------------------------------------------------------------------------------- /ftp_server/core/__pycache__/ftp_server.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Obsir/FTP/HEAD/ftp_server/core/__pycache__/ftp_server.cpython-36.pyc -------------------------------------------------------------------------------- /ftp_client/core/main.py: -------------------------------------------------------------------------------- 1 | # @Time : 2017/10/4 下午12:32 2 | # @Author : user_info 3 | 4 | 5 | from core import ftp_client 6 | 7 | def run(): 8 | client = ftp_client.FTPClient("localhost", 9999) 9 | client.start() -------------------------------------------------------------------------------- /ftp_server/bin/server.py: -------------------------------------------------------------------------------- 1 | # @Time : 2017/10/4 下午2:48 2 | # @Author : user_info 3 | 4 | 5 | import os 6 | import sys 7 | 8 | BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) 9 | sys.path.append(BASE_DIR) 10 | 11 | from core import main 12 | 13 | 14 | if __name__ == '__main__': 15 | main.run() -------------------------------------------------------------------------------- /ftp_client/bin/client.py: -------------------------------------------------------------------------------- 1 | # @Time : 2017/10/4 下午2:21 2 | # @Author : user_info 3 | 4 | 5 | import os 6 | import sys 7 | 8 | BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) 9 | sys.path.append(BASE_DIR) 10 | 11 | 12 | from core import main 13 | 14 | 15 | if __name__ == '__main__': 16 | main.run() -------------------------------------------------------------------------------- /ftp_server/core/update.py: -------------------------------------------------------------------------------- 1 | # @Time : 2017/10/4 下午9:07 2 | # @Author : Obser 3 | 4 | 5 | import json 6 | 7 | 8 | def update_available(user_info, available): 9 | with open(user_info) as f: 10 | info = json.load(f) 11 | info["available"] = available 12 | with open(user_info, "w") as f: 13 | json.dump(info, f) 14 | -------------------------------------------------------------------------------- /ftp_client/README: -------------------------------------------------------------------------------- 1 | ftp_client 2 | ├── README 3 | ├── bin # 执行文件 目录 4 | │   ├── __init__.py 5 | │   └── client.py # 客户端执行程序 6 | ├── conf # 配置文件 7 | │   └── __init__.py 8 | ├── core # 核心文件 目录 9 | │   ├── __init__.py 10 | │   ├── ftp_client.py # FTP客户端核心程序 11 | │   ├── main.py # 客户端启动程序 12 | │   └── protocol.py # 数据解析协议 13 | ├── data # 用户数据目录 14 | │   └── downloads # 用户下载目录 15 | └── log # 日志目录 16 | └── __init__.py -------------------------------------------------------------------------------- /ftp_server/core/main.py: -------------------------------------------------------------------------------- 1 | # @Time : 2017/10/2 下午5:10 2 | # @Author : Obser 3 | 4 | 5 | import socketserver 6 | 7 | from core import ftp_server 8 | 9 | 10 | def run(): 11 | HOST, PORT = "localhost", 9999 12 | 13 | # Create the server, binding to localhost on port 9999 14 | server = socketserver.ThreadingTCPServer((HOST, PORT), ftp_server.MyTCPHandler) 15 | 16 | # Activate the server; this will keep running until you 17 | # interrupt the program with Ctrl-C 18 | server.serve_forever() 19 | -------------------------------------------------------------------------------- /ftp_server/README: -------------------------------------------------------------------------------- 1 | ftp_server 2 | ├── README 3 | ├── bin 4 | │   ├── __init__.py 5 | │   └── server.py # 服务端执行程序 6 | ├── conf # 配置文件 7 | │   └── __init__.py 8 | ├── core # 核心文件 目录 9 | │   ├── __init__.py 10 | │   ├── ftp_server.py # FTP服务端核心程序 11 | │   ├── main.py # 服务端启动程序 12 | │   ├── protocol.py # 数据解析协议 13 | │   └── update.py # 更新服务端用户信息程序 14 | ├── data # 用户分配磁盘 15 | │   └── Obser # 示例用户 16 | │   ├── root # 用户存储空间根目录 17 | │   └── user_info # 用户信息文件 18 | └── log 19 | └── __init__.py 20 | 21 | 22 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | 作者:Obser 2 | 版本:测试版本 v0.1 3 | 程序介绍: 4 | 简单实现功能类似百度云盘的FTP程序 5 | 主要功能: 6 | 1. 用户登录,密码验证 7 | 2. 允许多用户同时在线 8 | 3. 每个用户有自己的根目录,且只能访问自己的根目录 9 | 4. 每个用户有属于自己的磁盘配额,每个用户的可用空间不同 10 | 5. 允许用户在FTP服务端随意切换目录 11 | 6. 允许用户查看当前目录下文件 12 | 7. 允许上传和下载文件 13 | 8. 文件传输过程中进度条实时显示 14 | 9. 允许用户在FTP服务端创建目录 15 | 10. 允许用户删除FTP服务端的文件 16 | 17 | 用户数据文件使用方法: 18 | · 在FTP服务端目录下的data文件中创建以用户名为目录名的文件夹 19 | · 其中详细文件和配置请参照实例用户的参数 20 | 21 | 22 | 程序结构: 23 | Obsir/ 24 | ├── README 25 | ├── ftp_client # FTP客户端代码 26 | │   ├── README 27 | │   ├── bin 28 | │   ├── conf 29 | │   ├── core 30 | │   ├── data 31 | │   └── log 32 | └── ftp_server # FTP服务端代码 33 | ├── README 34 | ├── bin 35 | ├── conf 36 | ├── core 37 | ├── data 38 | └── log -------------------------------------------------------------------------------- /ftp_client/core/protocol.py: -------------------------------------------------------------------------------- 1 | # @Time : 2017/10/4 下午1:58 2 | # @Author : user_info 3 | 4 | import json 5 | 6 | 7 | class Protocol(object): 8 | @staticmethod 9 | def json_put(filename, filesize, status="200", total=0, available=0): 10 | msg_dic = { 11 | "action": "put", 12 | "status": status, 13 | "filename": filename, 14 | "filesize": filesize, 15 | "total": total, 16 | "available": available 17 | } 18 | return json.dumps(msg_dic) 19 | 20 | @staticmethod 21 | def json_auth(account=None, password=None, status="200", total=0, available=0): 22 | msg_dic = { 23 | "action": "auth", 24 | "account": account, 25 | "password": password, 26 | "status": status, 27 | "total": total, 28 | "available": available 29 | } 30 | return json.dumps(msg_dic) 31 | 32 | @staticmethod 33 | def json_get(filename, filesize, status="200"): 34 | msg_dic = { 35 | "action": "get", 36 | "status": status, 37 | "filename": filename, 38 | "filesize": filesize 39 | } 40 | return json.dumps(msg_dic) 41 | 42 | @staticmethod 43 | def json_ls(resultsize=0, status="200"): 44 | msg_dic = { 45 | "action": "ls", 46 | "status": status, 47 | "resultsize": resultsize 48 | } 49 | return json.dumps(msg_dic) 50 | 51 | @staticmethod 52 | def json_pwd(status="200"): 53 | msg_dic = { 54 | "action": "pwd", 55 | "status": status 56 | } 57 | return json.dumps(msg_dic) 58 | 59 | @staticmethod 60 | def json_mkdir(cmd, status="200"): 61 | msg_dic = { 62 | "action": "mkdir", 63 | "status": status, 64 | "cmd": cmd 65 | } 66 | return json.dumps(msg_dic) 67 | 68 | @staticmethod 69 | def json_cd(dir_name, status="200"): 70 | msg_dic = { 71 | "action": "cd", 72 | "status": status, 73 | "dirname": dir_name 74 | } 75 | return json.dumps(msg_dic) 76 | 77 | @staticmethod 78 | def json_rm(filename=None, status="200", total=0, available=0): 79 | msg_dic = { 80 | "action": "rm", 81 | "status": status, 82 | "filename": filename, 83 | "total": total, 84 | "available": available 85 | } 86 | return json.dumps(msg_dic) -------------------------------------------------------------------------------- /ftp_server/core/protocol.py: -------------------------------------------------------------------------------- 1 | # @Time : 2017/10/4 下午1:58 2 | # @Author : user_info 3 | 4 | import json 5 | 6 | 7 | class Protocol(object): 8 | @staticmethod 9 | def json_put(filename, filesize, status="200", total=0, available=0): 10 | msg_dic = { 11 | "action": "put", 12 | "status": status, 13 | "filename": filename, 14 | "filesize": filesize, 15 | "total": total, 16 | "available": available 17 | } 18 | return json.dumps(msg_dic) 19 | 20 | @staticmethod 21 | def json_auth(account=None, password=None, status="200", total=0, available=0): 22 | msg_dic = { 23 | "action": "auth", 24 | "account": account, 25 | "password": password, 26 | "status": status, 27 | "total": total, 28 | "available": available 29 | } 30 | return json.dumps(msg_dic) 31 | 32 | @staticmethod 33 | def json_get(filename, filesize, status="200"): 34 | msg_dic = { 35 | "action": "get", 36 | "status": status, 37 | "filename": filename, 38 | "filesize": filesize 39 | } 40 | return json.dumps(msg_dic) 41 | 42 | @staticmethod 43 | def json_ls(resultsize=0, status="200"): 44 | msg_dic = { 45 | "action": "ls", 46 | "status": status, 47 | "resultsize": resultsize 48 | } 49 | return json.dumps(msg_dic) 50 | 51 | @staticmethod 52 | def json_pwd(status="200"): 53 | msg_dic = { 54 | "action": "pwd", 55 | "status": status 56 | } 57 | return json.dumps(msg_dic) 58 | 59 | @staticmethod 60 | def json_mkdir(cmd, status="200"): 61 | msg_dic = { 62 | "action": "mkdir", 63 | "status": status, 64 | "cmd": cmd 65 | } 66 | return json.dumps(msg_dic) 67 | 68 | @staticmethod 69 | def json_cd(dir_name, status="200"): 70 | msg_dic = { 71 | "action": "cd", 72 | "status": status, 73 | "dirname": dir_name 74 | } 75 | return json.dumps(msg_dic) 76 | 77 | @staticmethod 78 | def json_rm(filename=None, status="200", total=0, available=0): 79 | msg_dic = { 80 | "action": "rm", 81 | "status": status, 82 | "filename": filename, 83 | "total": total, 84 | "available": available 85 | } 86 | return json.dumps(msg_dic) -------------------------------------------------------------------------------- /ftp_server/core/ftp_server.py: -------------------------------------------------------------------------------- 1 | # @Time : 2017/10/4 下午9:25 2 | # @Author : Obser 3 | 4 | 5 | import socketserver 6 | import json 7 | import os 8 | from core import protocol 9 | from core import update 10 | 11 | BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) 12 | 13 | 14 | class MyTCPHandler(socketserver.BaseRequestHandler): 15 | def handle(self): 16 | while True: 17 | try: 18 | self.data = self.request.recv(1024).strip() 19 | if not self.data: 20 | break 21 | print("{} 发送请求:".format(self.client_address[0])) 22 | 23 | cmd_dic = json.loads(self.data.decode()) 24 | print(cmd_dic) 25 | action = cmd_dic["action"] 26 | if hasattr(self, action): 27 | func = getattr(self, action) 28 | func(cmd_dic) 29 | except Exception as e: 30 | pass 31 | 32 | def mkdir(self, *args): 33 | """ 34 | 创建目录 35 | :param args: 36 | :return: 37 | """ 38 | cmd_dic = args[0] 39 | cmd = cmd_dic["cmd"] 40 | os.popen(cmd) 41 | 42 | def pwd(self, *args): 43 | """ 44 | 显示当前路径 45 | :param args: 46 | :return: 47 | """ 48 | path = "root%s" % os.path.abspath(os.path.curdir).split(self.path)[1] 49 | self.request.send(path.encode()) 50 | 51 | def rm(self, *args): 52 | """ 53 | 删除指定文件 54 | :param args: 55 | :return: 56 | """ 57 | cmd_dic = args[0] 58 | filename = cmd_dic["filename"] 59 | if os.path.isfile(filename): 60 | filesize = os.path.getsize(filename) 61 | self.available += filesize 62 | update.update_available(self.user_file, self.available) 63 | os.remove(filename) 64 | self.request.send(protocol.Protocol.json_rm(status="200", total=self.total, available=self.available).encode()) 65 | else: 66 | self.request.send(protocol.Protocol.json_rm(status="404").encode()) 67 | 68 | def cd(self, *args): 69 | """ 70 | 进入指定目录 71 | :param args: 72 | :return: 73 | """ 74 | cmd_dic = args[0] 75 | dir_name = cmd_dic["dirname"] 76 | if dir_name == "..": 77 | if os.path.abspath(os.path.curdir) == self.path: 78 | path = self.path 79 | else: 80 | path = os.path.pardir 81 | elif dir_name.find("/") != -1: 82 | path = "%s/%s" % (self.path, dir_name) 83 | else: 84 | path = "%s/%s" % (os.path.abspath(os.path.curdir), dir_name) 85 | 86 | if os.path.isdir(path): 87 | os.chdir(path) 88 | self.request.send(protocol.Protocol.json_cd(os.path.curdir, status="200").encode()) 89 | else: 90 | self.request.send(protocol.Protocol.json_cd(os.path.curdir, status="404").encode()) 91 | 92 | def auth(self, *args): 93 | """ 94 | 客户端认证 95 | :param args: 96 | :return: 97 | """ 98 | cmd_dic = args[0] 99 | account = cmd_dic["account"] 100 | password = cmd_dic["password"] 101 | user_file = "%s/data/%s/user_info" % (BASE_DIR, account) 102 | if os.path.isfile(user_file): 103 | with open(user_file) as f: 104 | user_info = json.load(f) 105 | user_password = user_info["password"] 106 | if password == user_password: 107 | self.request.send(protocol.Protocol.json_auth(total=user_info["total"], 108 | available=user_info["available"]).encode()) 109 | os.chdir("%s/data/%s/root" % (BASE_DIR, account)) 110 | self.path = "%s/data/%s/root" % (BASE_DIR, account) 111 | self.total = user_info["total"] 112 | self.available = user_info["available"] 113 | self.user_file = user_file 114 | else: 115 | self.request.send(protocol.Protocol.json_auth(status="404").encode()) 116 | else: 117 | self.request.send(protocol.Protocol.json_auth(status="404").encode()) 118 | 119 | def ls(self, *args): 120 | """ 121 | 显示当前目录文件 122 | :param args: 123 | :return: 124 | """ 125 | cmd_dic = args[0] 126 | cmd = cmd_dic["action"] 127 | result = os.popen(cmd).read() 128 | self.request.send(protocol.Protocol.json_ls(resultsize=len(result)).encode()) 129 | client_response = self.request.recv(1024) 130 | self.request.send(result.encode()) 131 | 132 | def put(self, *args): 133 | """接收客户端上传的文件""" 134 | cmd_dic = args[0] 135 | filename = cmd_dic["filename"] 136 | filesize = cmd_dic["filesize"] 137 | if self.available - filesize < 0: 138 | self.request.send(protocol.Protocol.json_put(None, None, "300").encode()) 139 | else: 140 | if os.path.isfile(filename): 141 | self.available = self.available + os.path.getsize(filename) - filesize 142 | else: 143 | self.available -= filesize 144 | 145 | f = open(filename, "wb") 146 | self.request.send( 147 | protocol.Protocol.json_put(None, None, "200", total=self.total, available=self.available).encode()) 148 | received_size = 0 149 | while received_size < filesize: 150 | data = self.request.recv(1024) 151 | f.write(data) 152 | received_size += len(data) 153 | else: 154 | print("\033[32;1m文件 [%s] 上传完毕\033[0m" % filename) 155 | update.update_available(self.user_file, self.available) 156 | 157 | def get(self, *args): 158 | """向客户端发送文件""" 159 | cmd_dic = args[0] 160 | filename = cmd_dic["filename"] 161 | if os.path.isfile(filename): 162 | filesize = os.path.getsize(filename) 163 | json_msg_dic = protocol.Protocol.json_get(filename, filesize, status="200") 164 | self.request.send(json_msg_dic.encode()) 165 | client_response = self.request.recv(1024) 166 | with open(filename, "rb") as f: 167 | for line in f: 168 | self.request.send(line) 169 | else: 170 | print("\033[32;1m文件 [%s] 发送完毕\033[0m" % filename) 171 | else: 172 | json_msg_dic = protocol.Protocol.json_get(None, None, status="404") 173 | self.request.send(json_msg_dic.encode()) 174 | -------------------------------------------------------------------------------- /ftp_client/core/ftp_client.py: -------------------------------------------------------------------------------- 1 | # @Time : 2017/10/2 下午5:13 2 | # @Author : user_info 3 | import socket 4 | import os 5 | import json 6 | 7 | import sys 8 | 9 | import time 10 | from core import protocol 11 | BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) 12 | 13 | class FTPClient(object): 14 | def __init__(self, ip, port): 15 | self.client = socket.socket() 16 | self.ip = ip 17 | self.port = port 18 | 19 | def cmd_help(self, *args): 20 | msg = """\033[32;1m 21 | ------------可用命令------------ 22 | ls 列出当前目录下文件 23 | pwd 显示当前文件路径 24 | cd ../.. 进入指定目录 25 | get filename 下载指定文件 26 | put filename 上传指定文件 27 | mkdir filename 创建目录 28 | rm filename 删除指定文件 29 | exit 退出 30 | \033[0m""" 31 | print(msg) 32 | 33 | def cmd_rm(self, *args): 34 | """ 35 | 删除指定文件 36 | :param args: 37 | :return: 38 | """ 39 | cmd_split = args[0].split() 40 | if len(cmd_split) > 1: 41 | filename = cmd_split[1] 42 | self.client.send(protocol.Protocol.json_rm(filename).encode()) 43 | res_rm = json.loads(self.client.recv(1024).decode()) 44 | status = res_rm["status"] 45 | if status == "404": 46 | print("\033[31;1m文件不存在!\033[0m") 47 | elif status == "200": 48 | self.total = res_rm["total"] 49 | self.available = res_rm["available"] 50 | print("\033[32;1m文件删除成功\033[0m") 51 | print("\033[34;1m总大小为: \t%.2f MB \t(%d B)\033[0m" % (self.total / 1024 ** 2, self.total)) 52 | print("\033[33;1m可用空间为: \t%.2f MB \t(%d B)\033[0m" % (self.available / 1024 ** 2, self.available)) 53 | 54 | def cmd_mkdir(self, *args): 55 | """ 56 | 创建目录 57 | :param args: 58 | :return: 59 | """ 60 | cmd = args[0] 61 | cmd_split = cmd.split() 62 | if len(cmd_split) > 1: 63 | self.client.send(protocol.Protocol.json_mkdir(cmd).encode()) 64 | 65 | def cmd_cd(self, *args): 66 | """ 67 | 进入指定目录 68 | :param args: 69 | :return: 70 | """ 71 | cmd_split = args[0].split() 72 | if len(cmd_split) > 1: 73 | dir_name = cmd_split[1] 74 | self.client.send(protocol.Protocol.json_cd(dir_name).encode()) 75 | res_cd = json.loads(self.client.recv(1024).decode()) 76 | status = res_cd["status"] 77 | if status == "404": 78 | print("\033[31;1m目录不存在!\033[0m") 79 | 80 | def cmd_pwd(self, *args): 81 | """ 82 | 显示当前目录路径 83 | :param args: 84 | :return: 85 | """ 86 | self.client.send(protocol.Protocol.json_pwd().encode()) 87 | res_pwd = self.client.recv(1024).decode() 88 | print("\033[34;1m当前路径: %s\033[0m" % res_pwd) 89 | 90 | def cmd_exit(self, *args): 91 | """退出客户端""" 92 | exit() 93 | 94 | def start(self): 95 | """ 96 | 开启客户端 97 | :param ip: 98 | :param port: 99 | :return: 100 | """ 101 | self.__connect(self.ip, self.port) 102 | self.__auth() 103 | self.__interactive() 104 | 105 | def __connect(self, ip, port): 106 | """ 107 | 客户端连接服务端 108 | :param ip: 109 | :param port: 110 | :return: 111 | """ 112 | self.client.connect((ip, port)) 113 | 114 | def __auth(self): 115 | """ 116 | 客户端认证 117 | :return: 118 | """ 119 | account = input("请输入用户名>>:").strip() 120 | password = input("请输入密码>>:").strip() 121 | self.client.send(protocol.Protocol.json_auth(account, password).encode()) 122 | server_response = json.loads(self.client.recv(1024).decode()) 123 | status = server_response["status"] 124 | if status == "200": 125 | self.total = server_response["total"] 126 | self.available = server_response["available"] 127 | self.path = "%s/data/downloads" % BASE_DIR 128 | print("\033[34;1m总大小为: \t%.2f MB \t(%d B)\033[0m" % (self.total / 1024 ** 2, self.total)) 129 | print("\033[33;1m可用空间为: \t%.2f MB \t(%d B)\033[0m" % (self.available / 1024 ** 2, self.available)) 130 | else: 131 | print("\033[31;1m用户名或密码错误!\033[0m") 132 | self.cmd_exit() 133 | 134 | def __interactive(self): 135 | """ 136 | 连接成功后开启的交互程序 137 | :return: 138 | """ 139 | while True: 140 | cmd = input("请输入指令>>:").strip() 141 | if len(cmd) == 0: 142 | continue 143 | cmd_str = cmd.split()[0] 144 | if hasattr(self, "cmd_%s" % cmd_str): 145 | func = getattr(self, "cmd_%s" % cmd_str) 146 | func(cmd) 147 | else: 148 | self.cmd_help() 149 | 150 | def cmd_ls(self, *args): 151 | """ 152 | ls指令:列举当前目录下的文件 153 | :param args: 154 | :return: 155 | """ 156 | self.client.send(protocol.Protocol.json_ls().encode()) 157 | result_size = json.loads(self.client.recv(1024).decode()) 158 | self.client.send(protocol.Protocol.json_ls().encode()) 159 | size = result_size["resultsize"] 160 | received_size = 0 161 | while received_size < size: 162 | result = self.client.recv(1024).decode() 163 | received_size += len(result) 164 | print("\033[33;1m%s\033[0m" % result) 165 | 166 | def cmd_put(self, *args): 167 | """ 168 | 上传文件 169 | :param args: 170 | :return: 171 | """ 172 | cmd_split = args[0].split() 173 | if len(cmd_split) > 1: 174 | filepath = cmd_split[1] 175 | filename = filepath.split('/')[-1] 176 | if os.path.isfile(filepath): 177 | filesize = os.path.getsize(filepath) 178 | json_msg_dic = protocol.Protocol.json_put(filename, filesize) 179 | self.client.send(json_msg_dic.encode()) 180 | server_response = json.loads(self.client.recv(1024).decode()) # 防止粘包,等服务器确认 181 | status = server_response["status"] 182 | if status == "200": 183 | self.total = server_response["total"] 184 | self.available = server_response["available"] 185 | send_size = 0 186 | with open(filepath, "rb") as f: 187 | for line in f: 188 | self.client.send(line) 189 | send_size += len(line) 190 | self.progress(int(100 * (send_size / filesize))) 191 | else: 192 | print("\n\033[32;1m文件 [%s] 上传成功\033[0m" % filename) 193 | print("\033[34;1m总大小为: \t%.2f MB \t(%d B)\033[0m" % (self.total / 1024 ** 2, self.total)) 194 | print("\033[33;1m可用空间为: \t%.2f MB \t(%d B)\033[0m" % (self.available / 1024 ** 2, self.available)) 195 | elif status == "300": 196 | print("\033[33;1m可用空间为: \t%.2f MB \t(%d B)\033[0m" % (self.available / 1024 ** 2, self.available)) 197 | print("\033[31;1m当前文件大小为: \t%.2f MB \t(%d B)\033[0m" % (filesize / 1024 ** 2, filesize)) 198 | print("\033[31;1m可用空间不足!\033[0m") 199 | else: 200 | print("\033[31;1m文件 [%s] 不存在!\033[0m" % filename) 201 | 202 | def cmd_get(self, *args): 203 | """ 204 | 下载文件 205 | :param args: 206 | :return: 207 | """ 208 | cmd_split = args[0].split() 209 | if len(cmd_split) > 1: 210 | filename = cmd_split[1] 211 | filepath = "%s/%s" % (self.path, cmd_split[1]) 212 | self.client.send(protocol.Protocol.json_get(filename, 0).encode()) 213 | server_response = json.loads(self.client.recv(1024).decode()) 214 | status = server_response["status"] 215 | if status == "200": 216 | received_size = 0 217 | filesize = server_response["filesize"] 218 | self.client.send(protocol.Protocol.json_get(filename, filesize).encode()) 219 | with open(filepath, "wb") as f: 220 | while received_size < filesize: 221 | data = self.client.recv(1024) 222 | received_size += len(data) 223 | f.write(data) 224 | self.progress(int(100 * (received_size / filesize))) 225 | else: 226 | print("\n\033[32;1m文件 [%s] 下载完毕\033[0m" % filename) 227 | elif status == "404": 228 | print("\033[31;1m文件 [%s] 不存在!\033[0m" % filename) 229 | 230 | def progress(self, percent, width=50): 231 | """ 232 | 进度条打印 233 | :param width: 234 | :return: 235 | """ 236 | if percent >= 100: 237 | percent = 100 238 | show_str = ('[%%-%ds]' % width) % (int(width * percent / 100) * "#") # 字符串拼接的嵌套使用 239 | print("\033[32;1m\r%s %d%%\033[0m" % (show_str, percent), end='', file=sys.stdout, flush=True) 240 | --------------------------------------------------------------------------------