跳到内容
当前位置:首页>下载方法>Qt 多线程 HTTP 下载实战:线程池、限速与进度显示

Qt 多线程 HTTP 下载实战:线程池、限速与进度显示

  • 2026-10-14 06:31:25
Qt 多线程 HTTP 下载实战:线程池、限速与进度显示

Qt 多线程 HTTP 下载实战:线程池、限速与进度显示

在编程领域,多线程是提高程序执行效率和响应能力的一种常见技术,特别是在处理 I/O 密集型任务如网络下载时。Qt 是一个强大的跨平台应用程序开发框架,提供了丰富的 API 来支持多线程编程。本篇文章将深入讲解如何使用 Qt 的线程池实现多线程 HTTP 下载,并涵盖限速下载及进度显示的相关知识。

一、Qt 线程池(QThreadPool)机制

QThreadPool 是 Qt 提供的一个管理线程资源的类,它可以调度和执行异步任务,而无需程序员手动创建和管理线程。通过使用线程池,我们可以有效地避免频繁地创建和销毁线程带来的开销,同时确保系统资源的合理利用。

核心 API:

方法
说明
QThreadPool::globalInstance()
获取全局线程池单例
QThreadPool::start(QRunnable*)
提交任务到线程池
QThreadPool::setMaxThreadCount(int)
设置最大并发线程数
QThreadPool::waitForDone()
等待所有任务完成

二、实现多线程 HTTP 下载的关键步骤

1. 创建线程任务(继承 QRunnable)

定义一个继承自 QRunnable 的类,用于执行下载任务。这个类应包含下载 URL、目标保存路径等信息,以及执行下载的具体逻辑,比如使用 QNetworkAccessManager 发起 HTTP 请求并接收数据。

需要注意的是:**QNetworkAccessManager 必须在有事件循环的线程中运行**。因此 QRunnable 中需要自行创建一个 QEventLoop。

2. 使用线程池

在主线程中,实例化 QThreadPool,然后将创建的下载任务对象提交到线程池。

3. 限速下载

Qt 的 QNetworkAccessManager 本身没有直接限速接口,通常有两种思路:

  • 通过 QNetworkReply::setReadBufferSize() 限制缓冲区大小,间接影响读取速度;
  • 更精确的方式是:在 readyRead 信号中读取数据后,根据目标速率计算应休眠的时间,用 QThread::msleep() 控制节奏。

4. 设置网络上限(全局)

为了限制所有下载任务的总网络带宽,可以维护一个全局变量记录所有线程的总下载速度,在每个线程下载过程中实时更新。当达到设定的网络上限时,暂停或减缓某些线程的下载速度。

5. 单个线程限速

对于单个线程的下载速度限制,可以在每个下载任务中监控其下载速率,当超过设定值时,适当延迟数据读取,或分块下载以控制速度。

6. 实时显示下载速度

在主线程中,可以通过定时器定期查询各个线程的下载进度,计算出当前的平均下载速度,并在界面上进行展示。Qt 的信号槽机制天然适合这种跨线程通信。


三、完整代码示例

下面给出一个可运行的示例,包含主窗口、下载任务、限速逻辑和进度显示。

1. 下载任务类 DownloadTask

// downloadtask.h
#ifndef DOWNLOADTASK_H
#define DOWNLOADTASK_H

#include<QRunnable>
#include<QObject>
#include<QUrl>
#include<QString>
#include<atomic>

classQNetworkAccessManager;
classQNetworkReply;
classQFile;

// 全局下载速率统计(字节/秒),供所有任务更新
structGlobalRate {
staticstd::atomic<qint64> totalBytes;   // 累计字节
staticstd::atomic<int>    activeTasks;  // 活跃任务数
};

classDownloadTask :public QObject, public QRunnable
{
    Q_OBJECT
public:
    DownloadTask(const QUrl &url,
const QString &savePath,
                 qint64 maxBytesPerSec = 0,   // 单任务限速,0 表示不限
                 QObject *parent = nullptr);

voidrun()override;

signals:
voidprogress(qint64 received, qint64 total);
voidfinished(const QString &savePath, bool ok, const QString &err);
voidspeed(qint64 bytesPerSec);

private:
    QUrl    m_url;
    QString m_savePath;
    qint64  m_maxBytesPerSec;   // 单线程限速
std::atomic<bool> m_abort{false};

voidthrottle(qint64 chunkBytes, qint64 elapsedMs);
};

#endif// DOWNLOADTASK_H
// downloadtask.cpp
#include"downloadtask.h"
#include<QNetworkAccessManager>
#include<QNetworkRequest>
#include<QNetworkReply>
#include<QEventLoop>
#include<QFile>
#include<QTimer>
#include<QThread>
#include<QElapsedTimer>
#include<QDebug>

std::atomic<qint64> GlobalRate::totalBytes{0};
std::atomic<int>    GlobalRate::activeTasks{0};

DownloadTask::DownloadTask(const QUrl &url,
const QString &savePath,
                           qint64 maxBytesPerSec,
                           QObject *parent)
    : QObject(parent)
    , m_url(url)
    , m_savePath(savePath)
    , m_maxBytesPerSec(maxBytesPerSec)
{
    setAutoDelete(true);  // 任务结束后由线程池自动删除
}

voidDownloadTask::run()
{
// 每个 runnable 在自己的线程中运行,需要独立的 QNAM 和事件循环
    QNetworkAccessManager nam;
QNetworkRequest req(m_url);
    req.setAttribute(QNetworkRequest::RedirectPolicyAttribute,
                     QNetworkRequest::NoLessSafeRedirectPolicy);

    QNetworkReply *reply = nam.get(req);

// 通过信号槽连接(需 QEventLoop 驱动)
    QEventLoop loop;

QFile file(m_savePath);
if (!file.open(QIODevice::WriteOnly)) {
emit finished(m_savePath, false, "无法打开文件: " + file.errorString());
        reply->deleteLater();
return;
    }

    qint64 totalBytes    = -1;
    qint64 receivedBytes = 0;

// 用于限速:记录窗口内接收的字节与时间
    QElapsedTimer timer;
    timer.start();
    qint64 windowBytes = 0;
    qint64 windowStart = 0;

    GlobalRate::activeTasks.fetch_add(1);

    QObject::connect(reply, &QNetworkReply::readyRead, [&]() {
        QByteArray chunk = reply->readAll();
if (chunk.isEmpty()) return;

        file.write(chunk);
        receivedBytes += chunk.size();
        windowBytes   += chunk.size();

        GlobalRate::totalBytes.fetch_add(chunk.size());

// 单任务限速:每积攒约 64KB 检查一次
if (m_maxBytesPerSec > 0 && windowBytes >= 64 * 1024) {
            qint64 elapsed = timer.elapsed() - windowStart;
            qint64 expected = windowBytes * 1000 / m_maxBytesPerSec; // 应耗时 ms
if (elapsed < expected) {
                QThread::msleep(static_cast<unsignedlong>(expected - elapsed));
            }
            windowBytes = 0;
            windowStart = timer.elapsed();
        }

        emit progress(receivedBytes, totalBytes);
    });

// 定时上报瞬时速度
    QTimer speedTimer;
    QObject::connect(&speedTimer, &QTimer::timeout, [&]() {
static qint64 lastBytes = 0;
static qint64 lastMs    = 0;
        qint64 now = timer.elapsed();
        qint64 cur = receivedBytes;
if (now > lastMs) {
            qint64 bps = (cur - lastBytes) * 1000 / (now - lastMs);
            emit speed(bps);
            lastBytes = cur;
            lastMs    = now;
        }
    });
    speedTimer.start(500);

// 初始总大小
    QObject::connect(reply, &QNetworkReply::downloadProgress,
                     [&](qint64 rec, qint64 tot) {
        totalBytes = tot;
        emit progress(rec, tot);
    });

    QObject::connect(reply, &QNetworkReply::finished, [&]() {
        speedTimer.stop();
        loop.quit();
    });

    loop.exec();  // 阻塞当前线程,直到下载完成

bool ok = (reply->error() == QNetworkReply::NoError);
    QString err = ok ? QString() : reply->errorString();

    file.close();
    reply->deleteLater();

    GlobalRate::activeTasks.fetch_sub(1);
emit finished(m_savePath, ok, err);
}

2. 下载管理器(提交任务到线程池)

// downloadmanager.h
#ifndef DOWNLOADMANAGER_H
#define DOWNLOADMANAGER_H

#include<QObject>
#include<QThreadPool>
#include<QList>

classDownloadTask;

classDownloadManager :public QObject
{
    Q_OBJECT
public:
explicitDownloadManager(QObject *parent = nullptr);
    ~DownloadManager();

// 全局线程数上限
voidsetMaxThreads(int n){ m_pool->setMaxThreadCount(n); }

// 添加任务:单任务限速 maxBps(0 为不限)
DownloadTask* addDownload(const QString &url,
const QString &savePath,
                              qint64 maxBps = 0)
;

voidwaitForAll(){ m_pool->waitForDone(); }

signals:
voidtaskProgress(const QString &path, qint64 rec, qint64 total);
voidtaskFinished(const QString &path, bool ok, const QString &err);
voidtaskSpeed(const QString &path, qint64 bps);

private:
    QThreadPool *m_pool;
    QList<DownloadTask*> m_tasks;
};

#endif// DOWNLOADMANAGER_H
// downloadmanager.cpp
#include"downloadmanager.h"
#include"downloadtask.h"

DownloadManager::DownloadManager(QObject *parent)
    : QObject(parent)
{
    m_pool = new QThreadPool(this);
    m_pool->setMaxThreadCount(4);   // 默认 4 个并发线程
}

DownloadManager::~DownloadManager()
{
    m_pool->waitForDone();
}

DownloadTask* DownloadManager::addDownload(const QString &url,
const QString &savePath,
                                            qint64 maxBps)

{
auto *task = new DownloadTask(QUrl(url), savePath, maxBps, this);

    connect(task, &DownloadTask::progress, this,
            [this, savePath](qint64 rec, qint64 total) {
        emit taskProgress(savePath, rec, total);
    });
    connect(task, &DownloadTask::speed, this,
            [this, savePath](qint64 bps) {
        emit taskSpeed(savePath, bps);
    });
    connect(task, &DownloadTask::finished, this,
            [this, savePath](const QString &path, bool ok, const QString &err) {
        emit taskFinished(savePath, ok, err);
    });

    m_tasks.append(task);
    m_pool->start(task);   // 提交到线程池执行
return task;
}

3. 主窗口(进度与速度显示)

// mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include<QMainWindow>
#include<QHash>

classQTableWidget;
classQLineEdit;
classQPushButton;
classQSpinBox;
classQProgressBar;
classDownloadManager;

classMainWindow :public QMainWindow
{
    Q_OBJECT
public:
    MainWindow(QWidget *parent = nullptr);

private slots:
voidonAddClicked();
voidonProgress(const QString &path, qint64 rec, qint64 total);
voidonSpeed(const QString &path, qint64 bps);
voidonFinished(const QString &path, bool ok, const QString &err);

private:
introwOf(const QString &path);   // 根据保存路径查找行

    DownloadManager *m_mgr;
    QTableWidget    *m_table;
    QLineEdit       *m_urlEdit;
    QLineEdit       *m_pathEdit;
    QSpinBox        *m_threadSpin;
    QSpinBox        *m_speedSpin;    // 单任务限速 (KB/s)
    QPushButton     *m_addBtn;
};

#endif// MAINWINDOW_H
// mainwindow.cpp
#include"mainwindow.h"
#include"downloadmanager.h"
#include<QVBoxLayout>
#include<QHBoxLayout>
#include<QTableWidget>
#include<QHeaderView>
#include<QLineEdit>
#include<QPushButton>
#include<QLabel>
#include<QSpinBox>
#include<QFileDialog>
#include<QMessageBox>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    m_mgr = new DownloadManager(this);

// 顶部输入区
    m_urlEdit  = new QLineEdit(this);
    m_urlEdit->setPlaceholderText("http://example.com/file.zip");

    m_pathEdit = new QLineEdit(this);
    m_pathEdit->setPlaceholderText("保存路径");

auto *browseBtn = new QPushButton("浏览...", this);
    connect(browseBtn, &QPushButton::clicked, this, [this]{
        QString f = QFileDialog::getSaveFileName(this, "保存文件");
if (!f.isEmpty()) m_pathEdit->setText(f);
    });

    m_threadSpin = new QSpinBox(this);
    m_threadSpin->setRange(1, 32);
    m_threadSpin->setValue(4);
    m_threadSpin->setPrefix("线程: ");

    m_speedSpin = new QSpinBox(this);
    m_speedSpin->setRange(0, 100000);
    m_speedSpin->setValue(0);
    m_speedSpin->setSuffix(" KB/s (0=不限)");
    m_speedSpin->setPrefix("单任务限速: ");

    m_addBtn = new QPushButton("添加下载", this);

auto *top = new QHBoxLayout;
    top->addWidget(new QLabel("URL:", this));
    top->addWidget(m_urlEdit, 3);
    top->addWidget(new QLabel("路径:", this));
    top->addWidget(m_pathEdit, 3);
    top->addWidget(browseBtn);
    top->addWidget(m_threadSpin);
    top->addWidget(m_speedSpin);
    top->addWidget(m_addBtn);

// 下载列表
    m_table = new QTableWidget(this);
    m_table->setColumnCount(4);
    m_table->setHorizontalHeaderLabels({"文件", "进度", "速度", "状态"});
    m_table->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);

auto *central = new QWidget(this);
auto *v = new QVBoxLayout(central);
    v->addLayout(top);
    v->addWidget(m_table);
    setCentralWidget(central);
    resize(1000, 500);

    connect(m_addBtn, &QPushButton::clicked, this, &MainWindow::onAddClicked);

// 修改线程数
    connect(m_threadSpin, QOverload<int>::of(&QSpinBox::valueChanged),
this, [this](int n){ m_mgr->setMaxThreads(n); });

// 连接下载管理器信号
    connect(m_mgr, &DownloadManager::taskProgress,
this, &MainWindow::onProgress);
    connect(m_mgr, &DownloadManager::taskSpeed,
this, &MainWindow::onSpeed);
    connect(m_mgr, &DownloadManager::taskFinished,
this, &MainWindow::onFinished);
}

voidMainWindow::onAddClicked()
{
    QString url  = m_urlEdit->text().trimmed();
    QString path = m_pathEdit->text().trimmed();
if (url.isEmpty() || path.isEmpty()) {
        QMessageBox::warning(this, "提示", "请填写 URL 和保存路径");
return;
    }

    qint64 bps = m_speedSpin->value() * 1024LL;  // KB/s -> B/s
    m_mgr->addDownload(url, path, bps);

int row = m_table->rowCount();
    m_table->insertRow(row);
    m_table->setItem(row, 0, new QTableWidgetItem(path));
auto *bar = new QProgressBar(this);
    bar->setRange(0, 100);
    bar->setValue(0);
    m_table->setCellWidget(row, 1, bar);
    m_table->setItem(row, 2, new QTableWidgetItem("-"));
    m_table->setItem(row, 3, new QTableWidgetItem("下载中"));
}

intMainWindow::rowOf(const QString &path)
{
for (int i = 0; i < m_table->rowCount(); ++i) {
if (m_table->item(i, 0) && m_table->item(i, 0)->text() == path)
return i;
    }
return-1;
}

voidMainWindow::onProgress(const QString &path, qint64 rec, qint64 total)
{
int row = rowOf(path);
if (row < 0) return;
auto *bar = qobject_cast<QProgressBar*>(m_table->cellWidget(row, 1));
if (!bar) return;
if (total > 0) {
        bar->setRange(0, 100);
        bar->setValue(static_cast<int>(rec * 100 / total));
    } else {
        bar->setRange(0, 0);  // 未知总大小,转圈
    }
}

voidMainWindow::onSpeed(const QString &path, qint64 bps)
{
int row = rowOf(path);
if (row < 0) return;
    QString txt = QString::number(bps / 1024.0, 'f', 1) + " KB/s";
    m_table->item(row, 2)->setText(txt);
}

voidMainWindow::onFinished(const QString &path, bool ok, const QString &err)
{
int row = rowOf(path);
if (row < 0) return;
    m_table->item(row, 3)->setText(ok ? "完成" : ("失败: " + err));
}

4. 程序入口

// main.cpp
#include<QApplication>
#include"mainwindow.h"

intmain(int argc, char *argv[])
{
QApplication a(argc, argv);
    MainWindow w;
    w.show();
return a.exec();
}

四、设计要点解析

1. 关于 QRunnable 与信号槽

QRunnable 并非 QObject 子类,无法直接发出信号。示例中通过多重继承QObject + QRunnable 的方式解决了这个问题。需要注意:

  • setAutoDelete(true) 时,任务结束后由线程池释放,信号槽连接会随对象销毁而断开;
  • 若要跨线程通信,emit 时会自动使用队列连接,安全地投递到主线程。

2. 为什么每个任务要自己建 QNetworkAccessManager?

QNetworkAccessManager 内部依赖事件循环处理 I/O,且不是线程安全的。虽然官方允许在多个线程中使用同一 QNAM,但推荐每个线程一个 QNAM。因为 QRunnable 可能被调度到不同线程,所以示例在每个 run() 内部创建独立 QNAM,配合 QEventLoop 实现"同步风格"的下载逻辑。

3. 限速原理

限速的核心是"按目标速率控制单位时间内读写的字节数":

  • 记录一个时间窗口(如从 windowStart 开始);
  • 累计读到的字节 windowBytes;
  • 期望耗时 = windowBytes * 1000 / maxBytesPerSec 毫秒;
  • 若实际耗时小于期望耗时,就 QThread::msleep() 睡够差额。

这样既避免了把线程"卡死"在大量小 sleep 上,也能比较精确地控制速度。

4. 全局网络上限的思路

若想限制所有任务的总带宽,可以:

// 全局带宽控制器(示例)
classBandwidthLimiter {
public:
staticstd::atomic<qint64> maxTotalBps;   // 上限
staticstd::atomic<qint64> currentBps;    // 当前总量
};

每个任务在读取数据后更新 currentBps,如果超限,则在自己这一侧多 sleep 一会儿,直到全局速率回落。更高级的做法是使用令牌桶(Token Bucket)算法,把所有线程视作一个共享桶的消费者。

5. 进度与速度显示

  • 进度:QNetworkReply::downloadProgress(rec, total) 提供原始数据;readyRead 中也可以手动累加。
  • 速度:以固定间隔(如 500ms)采样一次累计字节数,差值除以时间即瞬时速度。
  • 跨线程通知:所有信号通过 DownloadManager 转发到主线程,UI 更新只在主线程执行,避免竞态。

五、扩展方向

在实际项目(如 httpdownloadtool)中,还可以进一步扩展:

  1. 断点续传:通过 HTTP Range 头请求部分数据,配合本地 .part 文件;
  2. 多线程分块下载同一文件:将文件按字节切分,多个 DownloadTask 分别下载对应区间,最后合并;
  3. 暂停/恢复:在任务中增加 abort 标志,配合 QNetworkReply::abort() 实现可控中断;
  4. 任务队列与优先级:使用 QThreadPool::tryStart() 和自定义任务优先级;
  5. 限速算法升级:用令牌桶替代简单 sleep,让限速更加平滑;
  6. UI 完善:添加全局速度显示、剩余时间估算、失败重试等。

六、总结

Qt 的线程池和网络模块为实现高效、可控的多线程 HTTP 下载提供了便利:

  • QThreadPool + QRunnable 让你无需手动管理线程生命周期;
  • QNetworkAccessManager + QEventLoop 让每个任务可以在独立线程中"同步"地完成 HTTP 请求;
  • 信号槽机制 天然适合跨线程更新 UI,实现进度与速度显示;
  • 限速策略 通过在数据读取路径上插入时间控制实现,可精确到单任务或全局。

通过合理设计和优化,我们可以创建一个既能充分利用系统资源,又能满足限速和进度显示需求的下载工具。这在日常的软件开发中是非常实用的技能,尤其是在处理大数据量的网络传输时。

基本 文件 流程 错误 SQL 调试
  1. 请求信息 : 2026-10-14 11:56:49 HTTP/1.1 GET : http://yeyulingfeng.com/a/495206.html
  2. 运行时间 : 0.072728s [ 吞吐率:13.75req/s ] 内存消耗:4,429.09kb 文件加载:140
  3. 缓存信息 : 0 reads,0 writes
  4. 会话信息 : SESSION_ID=164f725d8a814d2b88000a003d567e1a
  1. /www/wwwroot/yeyulingfeng.com/public/index.php ( 0.79 KB )
  2. /www/wwwroot/yeyulingfeng.com/vendor/autoload.php ( 0.17 KB )
  3. /www/wwwroot/yeyulingfeng.com/vendor/composer/autoload_real.php ( 2.49 KB )
  4. /www/wwwroot/yeyulingfeng.com/vendor/composer/platform_check.php ( 0.90 KB )
  5. /www/wwwroot/yeyulingfeng.com/vendor/composer/ClassLoader.php ( 14.03 KB )
  6. /www/wwwroot/yeyulingfeng.com/vendor/composer/autoload_static.php ( 4.90 KB )
  7. /www/wwwroot/yeyulingfeng.com/vendor/topthink/think-helper/src/helper.php ( 8.34 KB )
  8. /www/wwwroot/yeyulingfeng.com/vendor/topthink/think-validate/src/helper.php ( 2.19 KB )
  9. /www/wwwroot/yeyulingfeng.com/vendor/topthink/think-orm/src/helper.php ( 1.47 KB )
  10. /www/wwwroot/yeyulingfeng.com/vendor/topthink/think-orm/stubs/load_stubs.php ( 0.16 KB )
  11. /www/wwwroot/yeyulingfeng.com/vendor/topthink/framework/src/think/Exception.php ( 1.69 KB )
  12. /www/wwwroot/yeyulingfeng.com/vendor/topthink/think-container/src/Facade.php ( 2.71 KB )
  13. /www/wwwroot/yeyulingfeng.com/vendor/symfony/deprecation-contracts/function.php ( 0.99 KB )
  14. /www/wwwroot/yeyulingfeng.com/vendor/symfony/polyfill-mbstring/bootstrap.php ( 8.26 KB )
  15. /www/wwwroot/yeyulingfeng.com/vendor/symfony/polyfill-mbstring/bootstrap80.php ( 9.78 KB )
  16. /www/wwwroot/yeyulingfeng.com/vendor/symfony/var-dumper/Resources/functions/dump.php ( 1.49 KB )
  17. /www/wwwroot/yeyulingfeng.com/vendor/topthink/think-dumper/src/helper.php ( 0.18 KB )
  18. /www/wwwroot/yeyulingfeng.com/vendor/symfony/var-dumper/VarDumper.php ( 4.30 KB )
  19. /www/wwwroot/yeyulingfeng.com/vendor/topthink/framework/src/think/App.php ( 15.30 KB )
  20. /www/wwwroot/yeyulingfeng.com/vendor/topthink/think-container/src/Container.php ( 15.76 KB )
  21. /www/wwwroot/yeyulingfeng.com/vendor/psr/container/src/ContainerInterface.php ( 1.02 KB )
  22. /www/wwwroot/yeyulingfeng.com/app/provider.php ( 0.19 KB )
  23. /www/wwwroot/yeyulingfeng.com/vendor/topthink/framework/src/think/Http.php ( 6.04 KB )
  24. /www/wwwroot/yeyulingfeng.com/vendor/topthink/think-helper/src/helper/Str.php ( 7.29 KB )
  25. /www/wwwroot/yeyulingfeng.com/vendor/topthink/framework/src/think/Env.php ( 4.68 KB )
  26. /www/wwwroot/yeyulingfeng.com/app/common.php ( 0.03 KB )
  27. /www/wwwroot/yeyulingfeng.com/vendor/topthink/framework/src/helper.php ( 18.78 KB )
  28. /www/wwwroot/yeyulingfeng.com/vendor/topthink/framework/src/think/Config.php ( 5.54 KB )
  29. /www/wwwroot/yeyulingfeng.com/config/app.php ( 0.95 KB )
  30. /www/wwwroot/yeyulingfeng.com/config/cache.php ( 0.78 KB )
  31. /www/wwwroot/yeyulingfeng.com/config/console.php ( 0.23 KB )
  32. /www/wwwroot/yeyulingfeng.com/config/cookie.php ( 0.56 KB )
  33. /www/wwwroot/yeyulingfeng.com/config/database.php ( 2.50 KB )
  34. /www/wwwroot/yeyulingfeng.com/vendor/topthink/framework/src/think/facade/Env.php ( 1.67 KB )
  35. /www/wwwroot/yeyulingfeng.com/config/filesystem.php ( 0.61 KB )
  36. /www/wwwroot/yeyulingfeng.com/config/lang.php ( 0.91 KB )
  37. /www/wwwroot/yeyulingfeng.com/config/log.php ( 1.35 KB )
  38. /www/wwwroot/yeyulingfeng.com/config/middleware.php ( 0.19 KB )
  39. /www/wwwroot/yeyulingfeng.com/config/route.php ( 1.89 KB )
  40. /www/wwwroot/yeyulingfeng.com/config/session.php ( 0.57 KB )
  41. /www/wwwroot/yeyulingfeng.com/config/trace.php ( 0.34 KB )
  42. /www/wwwroot/yeyulingfeng.com/config/view.php ( 0.82 KB )
  43. /www/wwwroot/yeyulingfeng.com/app/event.php ( 0.25 KB )
  44. /www/wwwroot/yeyulingfeng.com/vendor/topthink/framework/src/think/Event.php ( 7.67 KB )
  45. /www/wwwroot/yeyulingfeng.com/app/service.php ( 0.13 KB )
  46. /www/wwwroot/yeyulingfeng.com/app/AppService.php ( 0.26 KB )
  47. /www/wwwroot/yeyulingfeng.com/vendor/topthink/framework/src/think/Service.php ( 1.64 KB )
  48. /www/wwwroot/yeyulingfeng.com/vendor/topthink/framework/src/think/Lang.php ( 7.35 KB )
  49. /www/wwwroot/yeyulingfeng.com/vendor/topthink/framework/src/lang/zh-cn.php ( 13.70 KB )
  50. /www/wwwroot/yeyulingfeng.com/vendor/topthink/framework/src/think/initializer/Error.php ( 3.31 KB )
  51. /www/wwwroot/yeyulingfeng.com/vendor/topthink/framework/src/think/initializer/RegisterService.php ( 1.33 KB )
  52. /www/wwwroot/yeyulingfeng.com/vendor/services.php ( 0.14 KB )
  53. /www/wwwroot/yeyulingfeng.com/vendor/topthink/framework/src/think/service/PaginatorService.php ( 1.52 KB )
  54. /www/wwwroot/yeyulingfeng.com/vendor/topthink/framework/src/think/service/ValidateService.php ( 0.99 KB )
  55. /www/wwwroot/yeyulingfeng.com/vendor/topthink/framework/src/think/service/ModelService.php ( 2.04 KB )
  56. /www/wwwroot/yeyulingfeng.com/vendor/topthink/think-trace/src/Service.php ( 0.77 KB )
  57. /www/wwwroot/yeyulingfeng.com/vendor/topthink/framework/src/think/Middleware.php ( 6.72 KB )
  58. /www/wwwroot/yeyulingfeng.com/vendor/topthink/framework/src/think/initializer/BootService.php ( 0.77 KB )
  59. /www/wwwroot/yeyulingfeng.com/vendor/topthink/think-orm/src/Paginator.php ( 11.86 KB )
  60. /www/wwwroot/yeyulingfeng.com/vendor/topthink/think-validate/src/Validate.php ( 63.20 KB )
  61. /www/wwwroot/yeyulingfeng.com/vendor/topthink/think-orm/src/Model.php ( 23.55 KB )
  62. /www/wwwroot/yeyulingfeng.com/vendor/topthink/think-orm/src/model/concern/Attribute.php ( 21.05 KB )
  63. /www/wwwroot/yeyulingfeng.com/vendor/topthink/think-orm/src/model/concern/AutoWriteData.php ( 4.21 KB )
  64. /www/wwwroot/yeyulingfeng.com/vendor/topthink/think-orm/src/model/concern/Conversion.php ( 6.44 KB )
  65. /www/wwwroot/yeyulingfeng.com/vendor/topthink/think-orm/src/model/concern/DbConnect.php ( 5.16 KB )
  66. /www/wwwroot/yeyulingfeng.com/vendor/topthink/think-orm/src/model/concern/ModelEvent.php ( 2.33 KB )
  67. /www/wwwroot/yeyulingfeng.com/vendor/topthink/think-orm/src/model/concern/RelationShip.php ( 28.29 KB )
  68. /www/wwwroot/yeyulingfeng.com/vendor/topthink/think-helper/src/contract/Arrayable.php ( 0.09 KB )
  69. /www/wwwroot/yeyulingfeng.com/vendor/topthink/think-helper/src/contract/Jsonable.php ( 0.13 KB )
  70. /www/wwwroot/yeyulingfeng.com/vendor/topthink/think-orm/src/model/contract/Modelable.php ( 0.09 KB )
  71. /www/wwwroot/yeyulingfeng.com/vendor/topthink/framework/src/think/Db.php ( 2.88 KB )
  72. /www/wwwroot/yeyulingfeng.com/vendor/topthink/think-orm/src/DbManager.php ( 8.52 KB )
  73. /www/wwwroot/yeyulingfeng.com/vendor/topthink/framework/src/think/Log.php ( 6.28 KB )
  74. /www/wwwroot/yeyulingfeng.com/vendor/topthink/framework/src/think/Manager.php ( 3.92 KB )
  75. /www/wwwroot/yeyulingfeng.com/vendor/psr/log/src/LoggerTrait.php ( 2.69 KB )
  76. /www/wwwroot/yeyulingfeng.com/vendor/psr/log/src/LoggerInterface.php ( 2.71 KB )
  77. /www/wwwroot/yeyulingfeng.com/vendor/topthink/framework/src/think/Cache.php ( 4.92 KB )
  78. /www/wwwroot/yeyulingfeng.com/vendor/psr/simple-cache/src/CacheInterface.php ( 4.71 KB )
  79. /www/wwwroot/yeyulingfeng.com/vendor/topthink/think-helper/src/helper/Arr.php ( 16.63 KB )
  80. /www/wwwroot/yeyulingfeng.com/vendor/topthink/framework/src/think/cache/driver/File.php ( 7.84 KB )
  81. /www/wwwroot/yeyulingfeng.com/vendor/topthink/framework/src/think/cache/Driver.php ( 9.03 KB )
  82. /www/wwwroot/yeyulingfeng.com/vendor/topthink/framework/src/think/contract/CacheHandlerInterface.php ( 1.99 KB )
  83. /www/wwwroot/yeyulingfeng.com/app/Request.php ( 0.09 KB )
  84. /www/wwwroot/yeyulingfeng.com/vendor/topthink/framework/src/think/Request.php ( 55.78 KB )
  85. /www/wwwroot/yeyulingfeng.com/app/middleware.php ( 0.25 KB )
  86. /www/wwwroot/yeyulingfeng.com/vendor/topthink/framework/src/think/Pipeline.php ( 2.61 KB )
  87. /www/wwwroot/yeyulingfeng.com/vendor/topthink/think-trace/src/TraceDebug.php ( 3.40 KB )
  88. /www/wwwroot/yeyulingfeng.com/vendor/topthink/framework/src/think/middleware/SessionInit.php ( 1.94 KB )
  89. /www/wwwroot/yeyulingfeng.com/vendor/topthink/framework/src/think/Session.php ( 1.80 KB )
  90. /www/wwwroot/yeyulingfeng.com/vendor/topthink/framework/src/think/session/driver/File.php ( 6.27 KB )
  91. /www/wwwroot/yeyulingfeng.com/vendor/topthink/framework/src/think/contract/SessionHandlerInterface.php ( 0.87 KB )
  92. /www/wwwroot/yeyulingfeng.com/vendor/topthink/framework/src/think/session/Store.php ( 7.12 KB )
  93. /www/wwwroot/yeyulingfeng.com/vendor/topthink/framework/src/think/Route.php ( 23.73 KB )
  94. /www/wwwroot/yeyulingfeng.com/vendor/topthink/framework/src/think/route/RuleName.php ( 5.75 KB )
  95. /www/wwwroot/yeyulingfeng.com/vendor/topthink/framework/src/think/route/Domain.php ( 2.53 KB )
  96. /www/wwwroot/yeyulingfeng.com/vendor/topthink/framework/src/think/route/RuleGroup.php ( 22.43 KB )
  97. /www/wwwroot/yeyulingfeng.com/vendor/topthink/framework/src/think/route/Rule.php ( 26.95 KB )
  98. /www/wwwroot/yeyulingfeng.com/vendor/topthink/framework/src/think/route/RuleItem.php ( 9.78 KB )
  99. /www/wwwroot/yeyulingfeng.com/route/app.php ( 1.72 KB )
  100. /www/wwwroot/yeyulingfeng.com/vendor/topthink/framework/src/think/facade/Route.php ( 4.70 KB )
  101. /www/wwwroot/yeyulingfeng.com/vendor/topthink/framework/src/think/route/dispatch/Controller.php ( 4.74 KB )
  102. /www/wwwroot/yeyulingfeng.com/vendor/topthink/framework/src/think/route/Dispatch.php ( 10.44 KB )
  103. /www/wwwroot/yeyulingfeng.com/app/controller/Index.php ( 5.22 KB )
  104. /www/wwwroot/yeyulingfeng.com/app/BaseController.php ( 2.05 KB )
  105. /www/wwwroot/yeyulingfeng.com/vendor/topthink/think-orm/src/facade/Db.php ( 0.93 KB )
  106. /www/wwwroot/yeyulingfeng.com/vendor/topthink/think-orm/src/db/connector/Mysql.php ( 5.44 KB )
  107. /www/wwwroot/yeyulingfeng.com/vendor/topthink/think-orm/src/db/PDOConnection.php ( 52.47 KB )
  108. /www/wwwroot/yeyulingfeng.com/vendor/topthink/think-orm/src/db/Connection.php ( 8.39 KB )
  109. /www/wwwroot/yeyulingfeng.com/vendor/topthink/think-orm/src/db/ConnectionInterface.php ( 4.57 KB )
  110. /www/wwwroot/yeyulingfeng.com/vendor/topthink/think-orm/src/db/builder/Mysql.php ( 16.58 KB )
  111. /www/wwwroot/yeyulingfeng.com/vendor/topthink/think-orm/src/db/Builder.php ( 24.06 KB )
  112. /www/wwwroot/yeyulingfeng.com/vendor/topthink/think-orm/src/db/BaseBuilder.php ( 27.50 KB )
  113. /www/wwwroot/yeyulingfeng.com/vendor/topthink/think-orm/src/db/Query.php ( 15.71 KB )
  114. /www/wwwroot/yeyulingfeng.com/vendor/topthink/think-orm/src/db/BaseQuery.php ( 45.13 KB )
  115. /www/wwwroot/yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/TimeFieldQuery.php ( 7.43 KB )
  116. /www/wwwroot/yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/AggregateQuery.php ( 3.26 KB )
  117. /www/wwwroot/yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/ModelRelationQuery.php ( 20.07 KB )
  118. /www/wwwroot/yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/ParamsBind.php ( 3.66 KB )
  119. /www/wwwroot/yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/ResultOperation.php ( 7.01 KB )
  120. /www/wwwroot/yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/WhereQuery.php ( 19.37 KB )
  121. /www/wwwroot/yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/JoinAndViewQuery.php ( 7.11 KB )
  122. /www/wwwroot/yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/TableFieldInfo.php ( 2.63 KB )
  123. /www/wwwroot/yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/Transaction.php ( 2.77 KB )
  124. /www/wwwroot/yeyulingfeng.com/vendor/topthink/framework/src/think/log/driver/File.php ( 5.96 KB )
  125. /www/wwwroot/yeyulingfeng.com/vendor/topthink/framework/src/think/contract/LogHandlerInterface.php ( 0.86 KB )
  126. /www/wwwroot/yeyulingfeng.com/vendor/topthink/framework/src/think/log/Channel.php ( 3.89 KB )
  127. /www/wwwroot/yeyulingfeng.com/vendor/topthink/framework/src/think/event/LogRecord.php ( 1.02 KB )
  128. /www/wwwroot/yeyulingfeng.com/vendor/topthink/think-helper/src/Collection.php ( 16.47 KB )
  129. /www/wwwroot/yeyulingfeng.com/vendor/topthink/framework/src/think/facade/View.php ( 1.70 KB )
  130. /www/wwwroot/yeyulingfeng.com/vendor/topthink/framework/src/think/View.php ( 4.39 KB )
  131. /www/wwwroot/yeyulingfeng.com/vendor/topthink/framework/src/think/Response.php ( 8.81 KB )
  132. /www/wwwroot/yeyulingfeng.com/vendor/topthink/framework/src/think/response/View.php ( 3.29 KB )
  133. /www/wwwroot/yeyulingfeng.com/vendor/topthink/framework/src/think/Cookie.php ( 6.06 KB )
  134. /www/wwwroot/yeyulingfeng.com/vendor/topthink/think-view/src/Think.php ( 8.38 KB )
  135. /www/wwwroot/yeyulingfeng.com/vendor/topthink/framework/src/think/contract/TemplateHandlerInterface.php ( 1.60 KB )
  136. /www/wwwroot/yeyulingfeng.com/vendor/topthink/think-template/src/Template.php ( 46.61 KB )
  137. /www/wwwroot/yeyulingfeng.com/vendor/topthink/think-template/src/template/driver/File.php ( 2.41 KB )
  138. /www/wwwroot/yeyulingfeng.com/vendor/topthink/think-template/src/template/contract/DriverInterface.php ( 0.86 KB )
  139. /www/wwwroot/yeyulingfeng.com/runtime/temp/44b959ca79ad33496f044db2c231b11d.php ( 8.29 KB )
  140. /www/wwwroot/yeyulingfeng.com/vendor/topthink/think-trace/src/Html.php ( 4.42 KB )
  1. CONNECT:[ UseTime:0.000656s ] mysql:host=172.18.0.4;port=3306;dbname=no_yeyulingfeng;charset=utf8mb4
  2. SHOW FULL COLUMNS FROM `fenlei` [ RunTime:0.000921s ]
  3. SELECT * FROM `fenlei` WHERE `fid` = 0 [ RunTime:0.000448s ]
  4. SELECT * FROM `fenlei` WHERE `fid` = 63 [ RunTime:0.000347s ]
  5. SHOW FULL COLUMNS FROM `set` [ RunTime:0.000522s ]
  6. SELECT * FROM `set` [ RunTime:0.000290s ]
  7. SHOW FULL COLUMNS FROM `article` [ RunTime:0.000618s ]
  8. SELECT * FROM `article` WHERE `id` = 495206 LIMIT 1 [ RunTime:0.000525s ]
  9. UPDATE `article` SET `lasttime` = 1791950209 WHERE `id` = 495206 [ RunTime:0.002247s ]
  10. SELECT * FROM `fenlei` WHERE `id` = 64 LIMIT 1 [ RunTime:0.000367s ]
  11. SELECT * FROM `article` WHERE `id` < 495206 ORDER BY `id` DESC LIMIT 1 [ RunTime:0.000438s ]
  12. SELECT * FROM `article` WHERE `id` > 495206 ORDER BY `id` ASC LIMIT 1 [ RunTime:0.000507s ]
  13. SELECT * FROM `article` WHERE `id` < 495206 ORDER BY `id` DESC LIMIT 10 [ RunTime:0.000765s ]
  14. SELECT * FROM `article` WHERE `id` < 495206 ORDER BY `id` DESC LIMIT 10,10 [ RunTime:0.000673s ]
  15. SELECT * FROM `article` WHERE `id` < 495206 ORDER BY `id` DESC LIMIT 20,10 [ RunTime:0.000607s ]
0.081625s