-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathclient.py
More file actions
159 lines (123 loc) · 5.2 KB
/
Copy pathclient.py
File metadata and controls
159 lines (123 loc) · 5.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
import argparse
import logging
import asyncio
import os
import json
import struct
import time
STORAGE_PATH = "./"
HOST, PORT = "127.0.0.1", 8888
class SocketListener:
_host = HOST
_port = PORT
def __init__(self, host=None, port=None):
if host:
self._host = host
if port:
self._port = port
async def send(self, msg: str):
self.writer.write(struct.pack('i', len(msg)))
await self.writer.drain()
self.writer.write(msg.encode())
await self.writer.drain()
async def send_content(self, content):
self.writer.write(content)
await self.writer.drain()
async def read_status(self):
r = await self.reader.read(4)
return struct.unpack('i', r)[0]
async def read_struct(self):
head_len = await self.reader.read(4)
head_len_value = struct.unpack('i', head_len)[0]
head_struct = await self.reader.read(head_len_value)
head_struct = json.loads(head_struct.decode())
return head_struct
async def __aenter__(self):
self.reader, self.writer = await asyncio.open_connection(self._host, self._port)
logging.info(f"{self._host}:{self._port} 连接成功!")
return self
async def __aexit__(self, *args):
await self.writer.drain()
self.writer.close()
await self.writer.wait_closed()
logging.info(f"{self._host}:{self._port} 关闭成功!")
class FinderCallback:
async def upload(self, root_path, file_paths):
async with SocketListener() as socket:
await socket.send("upload")
if await socket.read_status() != 200:
logging.info("无法上传!")
for file_path in file_paths:
with open(file_path, 'rb') as file:
content = file.read()
head_struct = {
"filename": os.path.relpath(file_path, root_path),
"filesize": len(content)
}
header = json.dumps(head_struct)
await socket.send(header)
rid = await socket.read_status()
if rid == 200:
logging.info(f"{file_path} 开始上传!")
# 发送文件内容
await socket.send_content(content)
elif rid == 409:
logging.info(f"{file_path} 服务端已存在!")
await socket.send("over")
async def download(self, filename):
async with SocketListener() as socket:
await socket.send("download")
r = await socket.read_status()
if r != 200:
logging.info("不允许下载!")
return
header = json.dumps({"filename": filename})
await socket.send(header)
rid = await socket.read_status()
if rid == 404:
logging.info(f"{filename} 文件不存在!")
return
if rid == 200:
head_struct = await socket.read_struct()
file_path = os.path.join(STORAGE_PATH, head_struct["filename"])
logging.info(f"{filename} 开始下载、存储目录 {file_path}")
with open(file_path, 'wb') as file:
filesize = int(head_struct["filesize"])
while filesize > 0:
data = await socket.reader.read(min(filesize, 2 ** 16))
file.write(data)
filesize -= len(data)
logging.info(f"{filename} 下载完成!")
class FileFinder:
def __init__(self, callback=None):
self.callback = callback or FinderCallback()
def list_files(self, file_dir):
if os.path.isfile(file_dir):
yield file_dir
else:
for p in os.listdir(file_dir):
yield from self.list_files(os.path.join(file_dir, p))
async def upload_file(self, file_path):
await self.callback.upload(os.path.dirname(file_path), self.list_files(file_path))
async def download_file(self, filename):
await self.callback.download(filename)
if __name__ == '__main__':
logging.basicConfig(level=logging.INFO, format="%(asctime)s - %(levelname)s: %(message)s", datefmt="%H:%M:%S")
parser = argparse.ArgumentParser()
parser.add_argument("-S", "--storage", help="存储地址", default=STORAGE_PATH, type=str, dest="storage")
parser.add_argument("-H", "--host", help="ip地址", default=HOST, type=str, dest="host")
parser.add_argument("-P", "--port", help="ip端口", default=PORT, type=int, dest="port")
parser.add_argument("-U", "--upload", help="上传文件", default=None, type=str, dest="upload")
parser.add_argument("-D", "--download", help="下载文件", default=None, type=str, dest="download")
args = parser.parse_args()
PORT = args.port
HOST = args.host
STORAGE_PATH = args.storage
start_time = time.time()
f = FileFinder()
if args.upload:
asyncio.run(f.upload_file(args.upload))
if args.download:
asyncio.run(f.download_file(args.download))
end_time = time.time()
logging.info(f"共耗时: {end_time - start_time}s")