Skip to content

Latest commit

 

History

History
343 lines (250 loc) · 7.28 KB

File metadata and controls

343 lines (250 loc) · 7.28 KB

文件上传超时和进度条改进

修改内容

1. 统一超时时间为5分钟

所有文件上传操作的超时时间统一改为 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分钟超时

2. 添加真实上传进度条

为所有文件上传功能添加了实时进度显示。

功能特性:

  • 实时进度:显示 0-100% 的真实上传进度
  • 详细信息:显示文件大小、已上传大小、百分比
  • 可取消:用户可以中途取消上传
  • 界面响应:上传过程中界面保持响应

修改的功能:

  1. 更新包上传 (server-gui/gui/widgets/update_dialog.py)

    • 添加进度回调
    • 实时显示上传进度
    • 支持取消上传
  2. 普通文件上传 (server-gui/gui/widgets/file_tab.py)

    • 添加进度回调
    • 实时显示上传进度
    • 支持取消上传
  3. API客户端 (server-gui/gui/api_client.py)

    • 添加 progress_callback 参数
    • 实现 UploadMonitor 类监控上传进度
  4. 更新管理器 (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%

[取消]

技术实现

UploadMonitor 类

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()

超时时间说明

为什么是5分钟?

文件大小 网速 预计上传时间
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 配置

确保 nginx 也配置了足够的超时时间:

http {
    # 文件上传大小限制
    client_max_body_size 500M;
    
    # 超时设置(建议比客户端长一些)
    client_body_timeout 360s;  # 6分钟
    proxy_read_timeout 360s;
    proxy_send_timeout 360s;
}

FastAPI/Uvicorn 配置

if __name__ == "__main__":
    import uvicorn
    uvicorn.run(
        "app.main:app",
        host="0.0.0.0",
        port=8000,
        timeout_keep_alive=360  # 6分钟
    )

测试建议

测试场景

  1. 小文件(< 1MB)

    • 应该几秒内完成
    • 进度条快速到100%
  2. 中等文件(10-50MB)

    • 应该在1-2分钟内完成
    • 进度条平滑增长
  3. 大文件(> 100MB)

    • 可能需要3-5分钟
    • 进度条持续更新
  4. 取消上传

    • 点击取消按钮
    • 应该立即停止并提示
  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=100

常见问题

Q1: 为什么不是10分钟?

A: 5分钟已经足够大多数场景。如果经常超时,应该:

  1. 检查网络速度
  2. 压缩文件
  3. 考虑分块上传

Q2: 进度条不准确?

A: 进度条显示的是已发送的字节数,不包括:

  • 网络传输时间
  • 服务器处理时间
  • 可能会在99%停留一会儿

Q3: 如何修改超时时间?

A: 修改代码中的 timeout=300 为其他值(秒)。

Q4: 能否断点续传?

A: 当前不支持。如果需要,可以实现分块上传(参考 CHUNKED_UPLOAD_SOLUTION.md)。

总结

改进点

  1. 统一超时时间:所有文件上传改为5分钟
  2. 添加进度条:实时显示上传进度
  3. 支持取消:用户可以中途取消
  4. 改善体验:清晰的进度和状态提示

影响的功能

  1. 更新包上传
  2. 普通文件上传
  3. 所有使用 api_client.upload_file() 的地方

需要重新打包

修改后需要重新打包服务端GUI:

cd server-gui
pyinstaller main.spec

现在上传大文件时,用户可以看到实时进度,体验更好!