所有文件上传操作的超时时间统一改为 300秒(5分钟)。
server-gui/gui/api_client.py
# 修改前
timeout=self.timeout # 10秒
# 修改后
timeout = 300 if files else self.timeout # 文件上传5分钟,其他10秒server-gui/gui/update_manager.py
timeout=300 # 5分钟超时为所有文件上传功能添加了实时进度显示。
- ✅ 实时进度:显示 0-100% 的真实上传进度
- ✅ 详细信息:显示文件大小、已上传大小、百分比
- ✅ 可取消:用户可以中途取消上传
- ✅ 界面响应:上传过程中界面保持响应
-
更新包上传 (
server-gui/gui/widgets/update_dialog.py)- 添加进度回调
- 实时显示上传进度
- 支持取消上传
-
普通文件上传 (
server-gui/gui/widgets/file_tab.py)- 添加进度回调
- 实时显示上传进度
- 支持取消上传
-
API客户端 (
server-gui/gui/api_client.py)- 添加
progress_callback参数 - 实现
UploadMonitor类监控上传进度
- 添加
-
更新管理器 (
server-gui/gui/update_manager.py)- 添加
progress_callback参数 - 实现
UploadMonitor类监控上传进度
- 添加
正在上传更新包到服务端...
文件大小: 25.50 MB
已上传: 12.75 MB (50%)
[████████████░░░░░░░░░░░░] 50%
[取消]
正在上传文件...
文件大小: 10.25 MB
已上传: 5.12 MB (50%)
[████████████░░░░░░░░░░░░] 50%
[取消]
class UploadMonitor:
def __init__(self, file_path, callback):
self.file_path = file_path
self.callback = callback
self.uploaded = 0
self.total = os.path.getsize(file_path)
def read(self, size=-1):
chunk = self.file.read(size)
if chunk:
self.uploaded += len(chunk)
if self.callback:
self.callback(self.uploaded, self.total)
return chunk
def __enter__(self):
self.file = open(self.file_path, 'rb')
return self
def __exit__(self, *args):
self.file.close()def update_progress(uploaded, total):
if progress.wasCanceled():
raise Exception("用户取消上传")
percent = int((uploaded / total) * 100)
progress.setValue(percent)
progress.setLabelText(
f"正在上传...\n"
f"已上传: {uploaded / 1024 / 1024:.2f} MB ({percent}%)"
)
# 保持界面响应
QApplication.processEvents()| 文件大小 | 网速 | 预计上传时间 |
|---|---|---|
| 10 MB | 1 Mbps | ~80秒 |
| 50 MB | 1 Mbps | ~400秒 (6.7分钟) |
| 100 MB | 1 Mbps | ~800秒 (13.3分钟) |
| 10 MB | 10 Mbps | ~8秒 |
| 50 MB | 10 Mbps | ~40秒 |
| 100 MB | 10 Mbps | ~80秒 |
5分钟(300秒) 适合:
- ✅ 10 Mbps 网速下上传 100MB+ 文件
- ✅ 1 Mbps 网速下上传 30MB 文件
- ✅ 大多数实际使用场景
| 操作类型 | 超时时间 | 说明 |
|---|---|---|
| 文件上传 | 300秒 (5分钟) | 大文件需要更长时间 |
| 普通API请求 | 10秒 | 快速响应 |
| 文件下载 | 300秒 (5分钟) | 客户端下载更新包 |
| WebSocket | 无限制 | 长连接 |
正在上传文件...
[不确定进度条,一直转圈]
用户不知道:
- ❌ 上传了多少
- ❌ 还需要多久
- ❌ 是否卡住了
- ❌ 能否取消
正在上传文件...
文件大小: 25.50 MB
已上传: 12.75 MB (50%)
[████████████░░░░░░░░░░░░] 50%
[取消]
用户清楚知道:
- ✅ 已上传多少
- ✅ 还剩多少
- ✅ 上传进度
- ✅ 可以取消
try:
result = upload_file(...)
except requests.exceptions.Timeout:
QMessageBox.critical(
self,
"上传超时",
"文件上传超时(超过5分钟)\n\n"
"可能原因:\n"
"1. 文件太大\n"
"2. 网络速度太慢\n"
"3. 服务器响应慢\n\n"
"建议:\n"
"- 检查网络连接\n"
"- 压缩文件后再上传\n"
"- 联系管理员"
)if progress.wasCanceled():
raise Exception("用户取消上传")
# 捕获异常
except Exception as e:
if "用户取消" in str(e):
QMessageBox.information(self, "已取消", "上传已取消")
else:
QMessageBox.critical(self, "错误", f"上传失败: {e}")确保 nginx 也配置了足够的超时时间:
http {
# 文件上传大小限制
client_max_body_size 500M;
# 超时设置(建议比客户端长一些)
client_body_timeout 360s; # 6分钟
proxy_read_timeout 360s;
proxy_send_timeout 360s;
}if __name__ == "__main__":
import uvicorn
uvicorn.run(
"app.main:app",
host="0.0.0.0",
port=8000,
timeout_keep_alive=360 # 6分钟
)-
小文件(< 1MB)
- 应该几秒内完成
- 进度条快速到100%
-
中等文件(10-50MB)
- 应该在1-2分钟内完成
- 进度条平滑增长
-
大文件(> 100MB)
- 可能需要3-5分钟
- 进度条持续更新
-
取消上传
- 点击取消按钮
- 应该立即停止并提示
-
网络中断
- 断开网络
- 应该超时并提示错误
# 创建测试文件
# 10MB
dd if=/dev/zero of=test_10mb.zip bs=1M count=10
# 50MB
dd if=/dev/zero of=test_50mb.zip bs=1M count=50
# 100MB
dd if=/dev/zero of=test_100mb.zip bs=1M count=100A: 5分钟已经足够大多数场景。如果经常超时,应该:
- 检查网络速度
- 压缩文件
- 考虑分块上传
A: 进度条显示的是已发送的字节数,不包括:
- 网络传输时间
- 服务器处理时间
- 可能会在99%停留一会儿
A: 修改代码中的 timeout=300 为其他值(秒)。
A: 当前不支持。如果需要,可以实现分块上传(参考 CHUNKED_UPLOAD_SOLUTION.md)。
- ✅ 统一超时时间:所有文件上传改为5分钟
- ✅ 添加进度条:实时显示上传进度
- ✅ 支持取消:用户可以中途取消
- ✅ 改善体验:清晰的进度和状态提示
- 更新包上传
- 普通文件上传
- 所有使用
api_client.upload_file()的地方
修改后需要重新打包服务端GUI:
cd server-gui
pyinstaller main.spec现在上传大文件时,用户可以看到实时进度,体验更好!