一个简单的使用例子
HttpClient client; client.get("https://qthub.com") .onSuccess([](QString result) { qDebug()<<"result:"<<result; }) .onFailed([](QString err) { qDebug()<<"error:"<<err; }) .exec();- 采用header-only的方式实现。只需在你的工程中包含 src 目录的 HttpClient.h 文件即可。
- Http请求返回成功的信号槽绑定
HttpRequest &onSuccess(const QObject *receiver, const char *method); HttpRequest &onSuccess(std::function<void (QNetworkReply*)> lambda); HttpRequest &onSuccess(std::function<void (QVariantMap)> lambda); HttpRequest &onSuccess(std::function<void (QByteArray)> lambda);- Http请求返回失败的信号槽绑定
HttpRequest &onFailed(const QObject *receiver, const char *method); HttpRequest &onFailed(std::function<void (QString)> lambda); HttpRequest &onFailed(std::function<void (QNetworkReply::NetworkError)> lambda); HttpRequest &onFailed(std::function<void (QNetworkReply*)> lambda);static HttpClient client; client.get("https://qthub.com") .onSuccess(this, SLOT(onSuccess(QString))) .onFailed(this, SLOT(onFailed(QString))) .exec(); // 执行Http操作- Http请求返回成功的回调事件
HttpRequest &onSuccess(std::function<void (QNetworkReply*)> lambda); HttpRequest &onSuccess(std::function<void (QVariantMap)> lambda); HttpRequest &onSuccess(std::function<void (QByteArray)> lambda);- Http请求返回失败的回调事件
HttpRequest &onFailed(std::function<void (QString)> lambda); HttpRequest &onFailed(std::function<void (QNetworkReply::NetworkError)> lambda); HttpRequest &onFailed(std::function<void (QNetworkReply*)> lambda);client.get("https://qthub.com") .onSuccess([](QString result) { qDebug()<<"result:"<<result.left(100); }) .onFailed([](QString error) { qDebug()<<"error:"<<error; }) .exec();HttpRequest &onDownloadProgress(const QObject *receiver, const char *method);client.get("https://qthub.com") .onSuccess(this, SLOT(onSuccess(QString))) .onDownloadProgress(this, SLOT(onDownloadProgress(qint64, qint64))) .onFailed(this, SLOT(onFailed(QString))) .exec();HttpRequest &onDownloadProgress(std::function<void (qint64, qint64)> lambda);client.get("https://qthub.com") .onSuccess([](QString result) { qDebug()<<"result: " << result.left(10); }) .onDownloadProgress([](qint64 bytesReceived, qint64 bytesTotal) { qDebug() << "lambda bytes received: " << bytesReceived << "bytes total: " << bytesTotal; }) .onFailed([](QString error) { qDebug()<<"error: " << error; }) .exec();HttpRequest &onUploadProgress(const QObject *receiver, const char *method); HttpRequest &onUploadProgress(std::function<void (qint64, qint64)> lambda);client.post("http://httpbin.org/post") .bodyWithFile("text_file", "helloworld.txt") .onUploadProgress([](qint64 bytesSent, qint64 bytesTotal) { qDebug() << "lambda bytes sent: " << bytesSent << "bytes total: " << bytesTotal; }) .onSuccess([](QString result) { qDebug()<<"result: " << result.left(100); }) .onFailed([](QString error) { qDebug()<<"error: " << error; }) .exec();- timeout(ms)是设置超时时间,单位为毫秒(ms)。
- onTimeout 为超时回调,当超时事件触发,自动调用 onTimeout 回调。
- 设置超时时间
HttpRequest &timeout(const int &msec = -1);- 设置超时的回调函数
HttpRequest &onTimeout(const QObject *receiver, const char *method); HttpRequest &onTimeout(std::function<void (QNetworkReply*)> lambda); HttpRequest &onTimeout(std::function<void ()> lambda);client.get("https://qthub.com") .onSuccess([](QString result) { qDebug()<<"result:"<<result.left(100); }) .onFailed([](QString error) { qDebug()<<"error:"<<error; }) .onTimeout([](QNetworkReply *) { qDebug()<<"timeout"; }) // 超时处理 .timeout(1000) // 1s超时 .exec();HttpRequest &block();client.get("https://qthub.com") .onSuccess(this, SLOT(onSuccess(QString))) .onFailed(this, SLOT(onFailed(QString))) .block() // 阻塞同步操作 .exec(); // 执行Http操作HttpRequest &header(const QString &key, const QVariant &value); HttpRequest &headers(const QMap<QString, QVariant> &headers);client.post("https://example.com") .header("content-type", "application/json") .queryParam("key", "Hello world!") .body(R"({"user": "test"})") .onSuccess([](QString result){}) .onFailed([](QString error){}) .exec();HttpRequest &queryParam(const QString &key, const QVariant &value); HttpRequest &queryParams(const QMap<QString, QVariant> ¶ms);client.get("https://example.com") .queryParam("key1", "value1") .queryParam("key2", "value2") .queryParam("key3", "value3") .onSuccess([](QString result){}) .onFailed([](QString error){}) .exec();上面代码等同于:
client.get("https://example.com?key1=value1&key2=value2&key3=value3") .onSuccess([](QString result){}) .onFailed([](QString error){})- 原始数据
HttpRequest &body(const QByteArray &raw); HttpRequest &bodyWithRaw(const QByteArray &raw);- json 数据
HttpRequest &body(const QJsonObject &json); HttpRequest &bodyWithJson(const QJsonObject &json);- 表单数据
HttpRequest &body(const QVariantMap &formUrlencodedMap); HttpRequest &bodyWithFormUrlencoded(const QVariantMap &keyValueMap);- 混合消息
HttpRequest &body(QHttpMultiPart *multiPart); HttpRequest &bodyWithMultiPart(QHttpMultiPart *multiPart);- 文件消息
HttpRequest &body(const QString &key, const QString &file); HttpRequest &bodyWithFile(const QString &key, const QString &file); HttpRequest &bodyWithFile(const QMap<QString/*key*/, QString/*file*/> &fileMap);client.post("http://httpbin.org/post") .body("hello world") .onSuccess([](QString result){qDebug()<<result;}) .onFailed([](QString error){qDebug()<<error;}) .exec();QJsonObject json { {"property1", 1}, {"property2", 2} }; client.post("http://httpbin.org/post") .body(json) .onSuccess([](QString result){qDebug()<<result;}) .onFailed([](QString error){qDebug()<<error;}) .exec();QVariantMap map { {"property1", 1}, {"property2", 2} }; client.post("http://httpbin.org/post") .body(map) .onSuccess([](QString result){qDebug()<<result;}) .onFailed([](QString error){qDebug()<<error;}) .exec(); QHttpMultiPart *multiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType); QFile *file = new QFile("demo.txt"); file->open(QIODevice::ReadOnly); file->setParent(multiPart); QString dispositionHeader = QString("form-data; name=\"%1\";filename=\"%2\"") .arg("text_file") .arg(file->fileName()); QHttpPart part; part.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("text/plain")); part.setHeader(QNetworkRequest::ContentDispositionHeader, dispositionHeader); part.setBodyDevice(file); multiPart->append(part); QString contentType = QString("multipart/form-data;boundary=%1").arg(multiPart->boundary().data()); HttpClient client; client.post("http://httpbin.org/post") .header("content-type", contentType) .body(multiPart) .onSuccess([](QString result){ qDebug()<<result.left(1000); }) .onFailed([](QString error){ qDebug()<<error; }) .exec();HttpClient client; client.post("http://httpbin.org/post") .body("text_file", "demo.txt") .body("image_file", "demo.jpg") .onSuccess([](QString result){ qDebug()<<result.left(1000); }) .onFailed([](QString error){ qDebug()<<error; }) .exec();HttpRequest &userAttribute(const QVariant &value);client.get("http://httpbin.org/get") .userAttribute("Hello world!") .onSuccess([](QNetworkReply *reply) { QVariant value = reply->request().attribute(QNetworkRequest::User); qDebug()<< value.toString(); }) .onFailed([](QString error){ qDebug()<<error; }) .exec();- 设置下载操作 保存为默认的文件名,会从请求头去拿文件名字,如果请求头没有则为链接最后的文本内容。
HttpRequest &download();指定保存的文件名字,可包含路径。
HttpRequest &download(const QString &file);- 下载成功或失败的响应回调/信号槽
HttpRequest &onDownloadSuccess(const QObject *receiver, const char *method); HttpRequest &onDownloadSuccess(std::function<void ()> lambda); HttpRequest &onDownloadSuccess(std::function<void (QString)> lambda); HttpRequest &onDownloadFailed(const QObject *receiver, const char *method); HttpRequest &onDownloadFailed(std::function<void ()> lambda); HttpRequest &onDownloadFailed(std::function<void (QString)> lambda);- 断点续传下载
默认开启断点续传下载功能,即当程序异常退出时,再次运行会接着从已下载的位置下载。
需要注意的是: 如果服务器不支持断点续传功能,则每次下载都是从头开始下载。
| 参数 | 解释 |
|---|---|
| enabled | 开启/关闭断点续传下载 |
HttpRequest &enabledBreakpointDownload(bool enabled = true);- 文件下载进度的响应回调/信号槽
回调传递的参数分别是已保存的文件字节数和文件总字节大小。
HttpRequest &onFileDownloadProgress(const QObject *receiver, const char *method); HttpRequest &onFileDownloadProgress(std::function<void (qint64, qint64)> lambda);- 简单下载文件
client.get("https://hub.fastgit.org/aeagean/QtNetworkService/archive/refs/heads/master.zip") .download("QtNetworkService.zip") .onDownloadSuccess([](QString fileName) { qDebug() << "Download completed: " << fileName; }) .onDownloadFailed([](QString error) { qDebug() << "Download failed: " << error; }) .exec();- 断点续传下载
client.get("http://mirrors.tuna.tsinghua.edu.cn/qt/archive/qt/6.0/6.0.3/single/qt-everywhere-src-6.0.3.tar.xz") .download() // 启用自动设置文件名字 => qt-everywhere-src-6.0.3.tar.xz .enabledBreakpointDownload() // 启用断点续传下载 .onFileDownloadProgress([](qint64 recv, qint64 total) { // 获取文件下载进度 qDebug().nospace() << (100 * qreal(recv)/total) << "%"; }) .onDownloadSuccess([](QString fileName) { // 下载成功 qDebug() << "Download completed: " << fileName; }) .onDownloadFailed([](QString error) { // 下载失败 qDebug() << "Download failed: " << error; }) .onSuccess([](QString result) { // 可省略 qDebug() << "success: " << result; }) .onFailed([](QString err) { // 可省略 qDebug() << "failed: " << err; }) .exec();设置失败请求后的重试次数,默认值为0。
HttpRequest &retry(int count);重试次数执行完成后的信号槽/回调。
HttpRequest &onRetried(const QObject *receiver, const char *method); HttpRequest &onRetried(std::function<void ()> lambda);client.get("xxx://httpbin.org/get") .retry(2) // 失败重试的次数 .onRetried([](){qDebug()<<"retried!";}) // 失败重试操作完成后的回调 .onSuccess([](QString result){qDebug()<<result;}) .onFailed([](QString err){qDebug()<<err;}) .exec();设置需要重复请求的次数,默认值为1。
HttpRequest &repeat(int count);重复请求完成后的信号槽/回调。
HttpRequest &onRepeated(const QObject *receiver, const char *method); HttpRequest &onRepeated(std::function<void ()> lambda);client.get("https://httpbin.org/get") .repeat(3) // 总共重复请求的次数 .onRepeated([](){qDebug()<<"repeated!";}) // 重复请求操作完成后的回调 .onSuccess([](QString result){qDebug()<<result;}) .onFailed([](QString err){qDebug()<<err;}) .exec();- 自动填写身份验证信息。注:当QNetworkAccessManager的authenticationRequired信号触发时,会自动往QAuthenticator填写用户名和密码信息。
HttpRequest &autoAuthenticationRequired(const QAuthenticator &authenticator); HttpRequest &autoAuthenticationRequired(const QString &user, const QString &password);- 通过回调/槽函数手动填写身份验证信息。
inline HttpRequest &onAuthenticationRequired(const QObject *receiver, const char *method); inline HttpRequest &onAuthenticationRequired(std::function<void (QAuthenticator *)> lambda);- 设置限制身份验证的次数,超过身份验证计数则触发失败并中断请求。
| 变量 | 解释 |
|---|---|
count < 0 | 不限制验证次数 |
count = 0 | 不验证 |
count = 1 | 限制验证1次(默认值) |
count > 0 | 限制count次 |
inline HttpRequest &authenticationRequiredCount(int count = 1);- 身份验证失败后错误回调。
inline HttpRequest &onAuthenticationRequireFailed(const QObject *receiver, const char *method); inline HttpRequest &onAuthenticationRequireFailed(std::function<void ()> lambda); inline HttpRequest &onAuthenticationRequireFailed(std::function<void (QNetworkReply *)> lambda);- 身份验证
client.get("https://httpbin.org/basic-auth/admin/123456") .onAuthenticationRequired([](QAuthenticator *authenticator) { authenticator->setUser("admin"); authenticator->setPassword("123456"); qDebug() << "============="; }) .onSuccess([](QString result){qDebug()<<"success: "<<result;}) .onFailed([](QString err){qDebug()<<"failed: "<<err;}) .exec();- 身份自动验证
client.get("https://httpbin.org/basic-auth/admin/123456") .autoAuthenticationRequired("admin", "123456") .onSuccess([](QString result){qDebug()<<"success: "<<result;}) .onFailed([](QString err){qDebug()<<"failed: "<<err;}) .exec();- 身份验证次数与错误处理
client.get("https://httpbin.org/basic-auth/admin/123456") .authenticationRequiredCount(2) // 最大重试验证次数为2次(默认值为1次) .onAuthenticationRequired([](QAuthenticator *authenticator) { authenticator->setUser("admin"); authenticator->setPassword("1234563"); // 错误输入 }) .onAuthenticationRequireFailed([](){ // 验证身份失败的回调 qDebug() << "authentication failed!"; }) .onSuccess([](QString result){qDebug()<<"success: "<<result;}) .onFailed([](QString err){qDebug()<<"failed: "<<err;}) .exec();autoAuthenticationRequired和onAuthenticationRequired不能同时使用,因为它们是互斥实现。如不慎同时使用,只会生效autoAuthenticationRequired操作。
Qt君
