You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用C++和Qt正确计算文件下载速度?

解决Qt下载速度计算持续增长的问题

问题根源

当前代码计算的是累计平均下载速度(总下载字节数 ÷ 总耗时),而非实时瞬时速度。随着下载进行,总字节数和总耗时同步增加,数值会一直向平均速率靠拢,无法反映当前真实的下载快慢。

解决方案

通过记录上一次回调的字节数和时间戳,计算两次downloadProgress回调之间的字节增量与时间增量,用增量比值得到这段时间内的瞬时速度,就能准确反映实时下载速率。

修改后的完整代码

class FileDownloader : public QObject
{
    Q_OBJECT
public:
    QNetworkAccessManager *manager;
    QByteArray downloadedData;
    QElapsedTimer downloadTimer;
    qint64 lastBytesRead = 0;  // 记录上一次的已下载字节数
    qint64 lastTimeMs = 0;     // 记录上一次的时间戳(毫秒)

    FileDownloader(const QUrl &url)
    {
        manager = new QNetworkAccessManager(this);
        QNetworkRequest request(url);
        QNetworkReply* reply = manager->get(request);
  
        connect(reply, &QNetworkReply::readyRead, this, [=]
        {
            downloadedData.append(reply->readAll());

            if (!downloadTimer.isValid())
                downloadTimer.start();
        });

        connect(reply, &QNetworkReply::downloadProgress, this, [this](qint64 bytesRead, qint64 totalBytes)
        {
            int perc = 0;
            if (totalBytes)
                perc = static_cast<int>((bytesRead * 100) / totalBytes);

            qDebug().nospace() << "\n" << perc << "% (" << bytesRead << "/" << totalBytes << ")";

            qint64 currentTimeMs = downloadTimer.elapsed();
            // 跳过第一次回调(无增量可计算)
            if (lastTimeMs > 0 && currentTimeMs > lastTimeMs)
            {
                qint64 bytesDelta = bytesRead - lastBytesRead;
                qint64 timeDeltaMs = currentTimeMs - lastTimeMs;

                // 计算瞬时速度(字节/秒)
                double speedBytesPerSec = bytesDelta / (timeDeltaMs / 1000.0);
                // 转换为常用单位(注:这里用1000进制,若需二进制单位可替换为1024)
                double speedKbps = speedBytesPerSec * 8 / 1000;
                double speedMbps = speedKbps / 1000;

                QString speedUnit;
                double speedValue;

                if (speedMbps >= 1.0)
                {
                    speedUnit = "MB/s";
                    speedValue = speedMbps;
                }
                else
                {
                    speedUnit = "KB/s";
                    speedValue = speedKbps;
                }

                qDebug().noquote() << "Download Speed:" << QString::number(speedValue, 'f', 2) << speedUnit;
            }

            // 更新上一次的记录值
            lastBytesRead = bytesRead;
            lastTimeMs = currentTimeMs;
        });
    }
};

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    
    QUrl url(
        "https://go.microsoft.com/fwlink/p/?LinkID=2208844&clcid=0x409&culture=en-us&country=US");
    FileDownloader fileDownloader(url);  

    return a.exec();
}

关键修改说明

  1. 添加lastBytesRead和lastTimeMs成员变量,用于存储上一次回调的状态
  2. 在downloadProgress中,仅当存在有效时间增量时计算速度,避免第一次回调的无效计算
  3. 用bytesDelta(字节增量)和timeDeltaMs(时间增量)计算瞬时速度,而非总总量除以总时间
  4. 每次回调结束后更新记录值,为下一次计算做准备

内容的提问来源于stack exchange,提问作者Nina

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 02:50:26