Skip to content

Commit d3b2c33

Browse files
Add UI Files
Add Qt UI Files
1 parent f97571a commit d3b2c33

57 files changed

Lines changed: 10733 additions & 0 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

tester/test.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import os
2+
import random
3+
4+
def generate_unity_compatible_binary(file_path, size=8192):
5+
"""
6+
生成可被Unity识别为TextAsset且仍以Hex视图打开的二进制文件
7+
关键:使用.bytes扩展名,同时保持非文本特征
8+
"""
9+
# 1. 保持反文本字节集(同之前的强二进制方案)
10+
anti_text_bytes = []
11+
anti_text_bytes.extend(range(1, 10)) # 0x01-0x09
12+
anti_text_bytes.extend(range(11, 32)) # 0x0B-0x1F
13+
anti_text_bytes.append(127) # DEL字符
14+
anti_text_bytes.extend(range(0xC0, 0xFF + 1)) # 高字节
15+
16+
# 2. 生成二进制数据(不含任何文本特征)
17+
binary_data = bytearray()
18+
for _ in range(size):
19+
while True:
20+
byte = random.choice(anti_text_bytes)
21+
# 避免连续相同字节
22+
if len(binary_data) >= 3 and byte == binary_data[-1] == binary_data[-2] == binary_data[-3]:
23+
continue
24+
# 禁止换行/回车
25+
if byte in (0x0D, 0x0A):
26+
continue
27+
break
28+
binary_data.append(byte)
29+
30+
# 3. 关键:使用.bytes扩展名(Unity会识别为TextAsset)
31+
if not file_path.endswith(".bytes"):
32+
file_path = os.path.splitext(file_path)[0] + ".bytes"
33+
34+
# 写入文件
35+
with open(file_path, 'wb') as f:
36+
f.write(binary_data)
37+
38+
print(f"已生成Unity兼容的二进制文件:{file_path},大小:{size}字节")
39+
40+
# 使用示例
41+
if __name__ == "__main__":
42+
# 必须使用.bytes扩展名
43+
generate_unity_compatible_binary("unity_binary.bytes", size=16384)

tester/test_server.py

Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
from flask import Flask, request, send_file, Response
2+
import os
3+
import time
4+
from threading import Lock
5+
6+
app = Flask(__name__)
7+
8+
# 限速配置 (10KB/s)
9+
LIMIT_BYTES_PER_SECOND = 100 * 1024 # 10KB
10+
CHUNK_SIZE = 1024 # 每次发送1KB
11+
SLEEP_INTERVAL = CHUNK_SIZE / LIMIT_BYTES_PER_SECOND # 每次发送后的休眠时间
12+
13+
# 存储要提供下载的文件目录
14+
UPLOAD_FOLDER = "files_to_serve"
15+
os.makedirs(UPLOAD_FOLDER, exist_ok=True)
16+
17+
# 用于控制并发下载的锁
18+
download_lock = Lock()
19+
20+
21+
def get_file_path(filename):
22+
"""获取文件的完整路径"""
23+
return os.path.join(UPLOAD_FOLDER, filename)
24+
25+
26+
def rate_limited_file_reader(file_path):
27+
"""生成器函数,限速读取文件内容"""
28+
with open(file_path, "rb") as f:
29+
while True:
30+
data = f.read(CHUNK_SIZE)
31+
if not data:
32+
break
33+
yield data
34+
# 控制速度:每发送CHUNK_SIZE字节后休眠相应时间
35+
time.sleep(SLEEP_INTERVAL)
36+
37+
38+
@app.route("/files/<filename>")
39+
def serve_file(filename):
40+
"""提供文件下载,限速10KB/s"""
41+
file_path = get_file_path(filename)
42+
43+
# 检查文件是否存在
44+
if not os.path.exists(file_path):
45+
return f"文件 {filename} 不存在", 404
46+
47+
# 获取文件大小
48+
file_size = os.path.getsize(file_path)
49+
50+
# 设置响应头
51+
headers = {
52+
"Content-Disposition": f'attachment; filename="{filename}"',
53+
"Content-Length": str(file_size),
54+
"Accept-Ranges": "bytes", # 支持断点续传
55+
}
56+
57+
# 使用限速生成器提供文件内容
58+
return Response(
59+
rate_limited_file_reader(file_path),
60+
headers=headers,
61+
mimetype="application/octet-stream",
62+
)
63+
64+
65+
@app.route("/range-test/<filename>")
66+
def range_test(filename):
67+
"""测试断点续传支持的端点"""
68+
file_path = get_file_path(filename)
69+
70+
if not os.path.exists(file_path):
71+
return f"文件 {filename} 不存在", 404
72+
73+
file_size = os.path.getsize(file_path)
74+
range_header = request.headers.get("Range", None)
75+
76+
# 如果没有Range头,返回完整文件
77+
if not range_header:
78+
headers = {
79+
"Content-Disposition": f'attachment; filename="{filename}"',
80+
"Content-Length": str(file_size),
81+
"Accept-Ranges": "bytes",
82+
}
83+
return Response(
84+
rate_limited_file_reader(file_path),
85+
headers=headers,
86+
mimetype="application/octet-stream",
87+
)
88+
89+
# 处理Range请求
90+
try:
91+
# 解析Range头 (格式: bytes=start-end)
92+
range_start, range_end = range_header.replace("bytes=", "").split("-")
93+
range_start = int(range_start)
94+
range_end = int(range_end) if range_end else file_size - 1
95+
96+
# 确保范围有效
97+
if range_start > range_end or range_start >= file_size:
98+
return "Invalid range", 416
99+
100+
# 调整结束范围
101+
range_end = min(range_end, file_size - 1)
102+
103+
# 生成部分文件内容的生成器
104+
def limited_range_reader():
105+
with open(file_path, "rb") as f:
106+
f.seek(range_start)
107+
remaining = range_end - range_start + 1
108+
while remaining > 0:
109+
read_size = min(remaining, CHUNK_SIZE)
110+
data = f.read(read_size)
111+
if not data:
112+
break
113+
yield data
114+
remaining -= read_size
115+
time.sleep(SLEEP_INTERVAL)
116+
117+
# 返回部分内容
118+
headers = {
119+
"Content-Disposition": f'attachment; filename="{filename}"',
120+
"Content-Range": f"bytes {range_start}-{range_end}/{file_size}",
121+
"Content-Length": str(range_end - range_start + 1),
122+
"Accept-Ranges": "bytes",
123+
}
124+
125+
return Response(
126+
limited_range_reader(),
127+
status=206, # Partial Content
128+
headers=headers,
129+
mimetype="application/octet-stream",
130+
)
131+
132+
except Exception as e:
133+
return f"处理范围请求时出错: {str(e)}", 400
134+
135+
136+
@app.route("/no-range/<filename>")
137+
def no_range_serve(filename):
138+
"""提供文件下载但不支持断点续传,用于测试兼容性"""
139+
file_path = get_file_path(filename)
140+
141+
if not os.path.exists(file_path):
142+
return f"文件 {filename} 不存在", 404
143+
144+
file_size = os.path.getsize(file_path)
145+
146+
# 不设置Accept-Ranges头,表示不支持断点续传
147+
headers = {
148+
"Content-Disposition": f'attachment; filename="{filename}"',
149+
"Content-Length": str(file_size),
150+
# 注意:这里没有设置Accept-Ranges头
151+
}
152+
153+
return Response(
154+
rate_limited_file_reader(file_path),
155+
headers=headers,
156+
mimetype="application/octet-stream",
157+
)
158+
159+
160+
if __name__ == "__main__":
161+
print(f"限速文件服务器启动中...")
162+
print(
163+
f"限速: {LIMIT_BYTES_PER_SECOND} bytes/s ({LIMIT_BYTES_PER_SECOND/1024:.2f}KB/s)"
164+
)
165+
print(f"请将测试文件放入 {UPLOAD_FOLDER} 目录")
166+
print(f"访问 http://localhost:5000/files/文件名 以下载文件(支持断点续传)")
167+
print(f"访问 http://localhost:5000/no-range/文件名 以下载文件(不支持断点续传)")
168+
app.run(host="0.0.0.0", port=5000, debug=True)

uip/__init__.py

Whitespace-only changes.
148 Bytes
Binary file not shown.
8.39 KB
Binary file not shown.
29 KB
Binary file not shown.
14.7 KB
Binary file not shown.
6.12 KB
Binary file not shown.
7.71 KB
Binary file not shown.
4.62 KB
Binary file not shown.

0 commit comments

Comments
 (0)