草庐IT

QT(17)- QNetworkAccessManager

m晴朗 2023-11-29 原文

QT(17)- QNetworkAccessManager

1 简介

QNetworkAccessManager是Qt网络模块中的一个类,它用于管理网络请求和响应。它可以发送HTTP请求,处理HTTP响应,支持文件上传和下载,以及支持多种网络协议。

QNetworkAccessManager使用异步方式发送请求和处理响应,这意味着它可以在不阻塞应用程序UI线程的情况下进行网络通信。当一个请求被发送时,QNetworkAccessManager将立即返回一个QNetworkReply对象,该对象可以用于监视请求的进度,访问响应数据以及处理响应错误。

QNetworkAccessManager可以使用各种不同的请求类型,包括GET、POST、PUT、DELETE等。它还支持设置请求头、查询参数、表单数据等,以及可以设置代理服务器。

使用QNetworkAccessManager发送HTTP请求的基本流程如下:

  • 创建QNetworkAccessManager对象
  • 创建QNetworkRequest对象,设置请求URL和请求头
  • 使用QNetworkAccessManager的get()、post()、put()等函数发送请求
  • 处理QNetworkReply对象以获取响应数据

QNetworkAccessManager可以方便地集成到Qt应用程序中,使应用程序可以与远程服务器进行通信。

2 公有类型

3 函数

3.1 addStrictTransportSecurityHosts

void addStrictTransportSecurityHosts(const QVector<QHstsPolicy> &knownHosts)
addStrictTransportSecurityHosts是QNetworkConfigurationManager类中的一个函数,用于向已知主机列表中添加HSTS(HTTP Strict Transport Security)策略。

HSTS是一种Web安全策略,通过HTTP响应头告知浏览器只能使用HTTPS连接来访问该网站,从而提高安全性。在服务器发送HSTS响应头后,浏览器将在一段时间内(通常是几个月)内记住该主机的HSTS策略,并自动将所有未来的HTTP请求重定向到HTTPS。当然,这仅适用于已经使用过HTTPS的站点。

在Qt中,可以使用QHstsPolicy类来表示一个主机的HSTS策略,其构造函数接受一个主机名和一个时间戳参数。可以通过调用addStrictTransportSecurityHosts函数向QNetworkConfigurationManager添加一个或多个已知的主机的HSTS策略,从而增强应用程序的网络安全性。

函数参数knownHosts是一个QVector类型的向量,包含要添加的主机列表。

3.2 autoDeleteReplies

bool QNetworkAccessManager::autoDeleteReplies() const
QNetworkAccessManager::autoDeleteReplies()是一个函数,用于返回当前QNetworkAccessManager是否配置为自动删除QNetworkReply对象。如果设置为自动删除,QNetworkAccessManager将在QNetworkReply对象完成后自动删除该对象,否则QNetworkReply对象需要手动删除。

该函数在Qt 5.14版本中引入。

默认情况下,QNetworkAccessManager的自动删除QNetworkReply的功能是启用的,这意味着当QNetworkReply对象完成后,QNetworkAccessManager将自动删除该对象。如果你想手动管理QNetworkReply对象的生命周期,可以通过调用QNetworkAccessManager的setAutoDeleteReplies(false)来禁用自动删除功能,然后手动删除QNetworkReply对象

3.3 cache

QAbstractNetworkCache *QNetworkAccessManager::cache() const
QNetworkAccessManager::cache()是一个函数,用于获取QNetworkAccessManager使用的网络数据缓存。返回的是一个指向QAbstractNetworkCache对象的指针。

QNetworkAccessManager可以使用缓存来存储从网络获取的数据,从而避免重复下载数据。如果应用程序需要在多个网络请求之间共享数据,可以使用缓存。默认情况下,QNetworkAccessManager使用QNetworkDiskCache类来管理网络数据缓存,该类将缓存数据保存在磁盘上。可以使用setCache()函数来设置其他类型的缓存,例如QNetworkMemoryCache,该类将缓存数据保存在内存中。

void QNetworkAccessManager::setCache(QAbstractNetworkCache *cache)
QNetworkAccessManager::setCache()是一个函数,用于设置QNetworkAccessManager使用的网络数据缓存。可以通过传递指向QAbstractNetworkCache对象的指针来设置缓存。QNetworkAccessManager将在处理所有网络请求时使用指定的缓存。需要注意的是,QNetworkAccessManager将拥有缓存对象的所有权,并负责在合适的时间删除缓存对象。

默认情况下,QNetworkAccessManager没有设置网络数据缓存。可以使用setCache()函数来设置其他类型的缓存,例如QNetworkMemoryCache或QNetworkDiskCache。设置网络数据缓存可以提高应用程序的性能,因为这样可以避免重复下载数据

3.4 clearAccessCache

void QNetworkAccessManager::clearAccessCache()
QNetworkAccessManager::clearAccessCache()是一个函数,用于刷新QNetworkAccessManager内部的身份验证数据和网络连接缓存。该函数通常用于自动化测试等情况下,需要清空缓存来进行多个独立测试的场合。

QNetworkAccessManager维护一个内部缓存,用于存储身份验证信息和网络连接信息,以便在未来的请求中重用这些信息。在某些情况下,可能需要清空这些缓存,例如在进行多个独立测试时,以确保每个测试的环境都是独立的。

以下是一个示例代码,展示了如何使用QNetworkAccessManager::clearAccessCache()函数清空访问缓存:

QNetworkAccessManager *manager = new QNetworkAccessManager();
// 向manager发送请求,填充缓存

// 执行测试
// ...

// 清空缓存
manager->clearAccessCache();

// 执行下一个测试
// ...

delete manager;

在这个示例中,我们首先创建一个QNetworkAccessManager对象,并发送一些请求,以填充内部缓存。然后,执行一些测试代码,之后调用clearAccessCache()函数清空访问缓存,以确保下一个测试环境是独立的。需要注意的是,clearAccessCache()函数只清空身份验证数据和网络连接信息的缓存,而不会清空其他缓存,例如DNS缓存或网络数据缓存。如果需要清空其他缓存,请使用相关的函数,例如QNetworkDiskCache::clear()函数。

3.5 clearConnectionCache

void QNetworkAccessManager::clearConnectionCache()
QNetworkAccessManager::clearConnectionCache()是一个函数,用于刷新QNetworkAccessManager内部的网络连接缓存。与clearAccessCache()不同的是,该函数保留身份验证数据。

该函数在Qt 5.9版本中引入。

QNetworkAccessManager维护一个内部缓存,用于存储网络连接信息,以便在未来的请求中重用这些信息。在某些情况下,可能需要清空这些缓存,例如在进行多个独立测试时,以确保每个测试的环境都是独立的。与clearAccessCache()不同,clearConnectionCache()只清空网络连接缓存,而保留身份验证数据。

3.6 connectToHost

void QNetworkAccessManager::connectToHost(const QString &hostName, quint16 port = 80)
QNetworkAccessManager::connectToHost()是一个函数,用于在发起HTTP请求之前,建立到指定主机的TCP连接。该函数可以降低网络延迟,提高HTTP请求的响应速度。

该函数在Qt 5.2版本中引入。

QNetworkAccessManager默认是在HTTP请求时,自动建立到目标主机的TCP连接。这意味着当你发起HTTP请求时,QNetworkAccessManager会自动完成TCP握手,建立TCP连接,并在该连接上发送HTTP请求。使用connectToHost()函数可以在发起HTTP请求之前,手动建立到主机的TCP连接,从而降低网络延迟。

需要注意的是,connectToHost()函数没有错误报告的可能性,因此,建议使用QNetworkAccessManager默认的自动连接功能,除非你有充分的理由需要手动建立TCP连接。

以下是一个示例代码,展示了如何使用QNetworkAccessManager::connectToHost()函数手动建立到主机的TCP连接:

QNetworkAccessManager *manager = new QNetworkAccessManager();

// 建立到主机的TCP连接
manager->connectToHost("www.example.com", 80);

// 发起HTTP请求
QNetworkReply *reply = manager->get(QNetworkRequest(QUrl("http://www.example.com")));
connect(reply, &QNetworkReply::finished, this, [reply]() {
    // 处理响应数据
    QByteArray data = reply->readAll();
    qDebug() << "Received data:" << data;
});
delete manager;

在这个示例中,我们首先创建一个QNetworkAccessManager对象,然后使用connectToHost()函数手动建立到主机的TCP连接。接着发送一个GET请求,获取QNetworkReply对象,并处理响应数据。需要注意的是,由于connectToHost()函数没有错误报告的可能性,因此必须在发起HTTP请求之前,确保TCP连接已经成功建立。如果TCP连接未能成功建立,则可能导致HTTP请求失败或超时。

3.7 connectToHostEncrypted

void connectToHostEncrypted(const QString &hostName, quint16 port = 443, const QSslConfiguration &sslConfiguration = QSslConfiguration::defaultConfiguration())

void connectToHostEncrypted(const QString &hostName, quint16 port, const QSslConfiguration &sslConfiguration, const QString &peerName)
QNetworkAccessManager::connectToHostEncrypted()是一个函数,用于在发起HTTPS请求之前,建立到指定主机的安全TCP连接。该函数可以手动建立到主机的安全TCP连接,从而提高HTTPS请求的响应速度。

该函数可以有两个版本,其中一个版本需要提供peerName参数,用于验证服务器的证书。

这两个函数在Qt 4.6版本中引入。

QNetworkAccessManager默认情况下是在HTTPS请求时,自动建立到目标主机的安全TCP连接。这意味着当你发起HTTPS请求时,QNetworkAccessManager会自动完成SSL握手,建立安全TCP连接,并在该连接上发送HTTPS请求。使用connectToHostEncrypted()函数可以在发起HTTPS请求之前,手动建立到主机的安全TCP连接,从而提高HTTPS请求的响应速度。

以下是一个示例代码,展示了如何使用QNetworkAccessManager::connectToHostEncrypted()函数手动建立到主机的安全TCP连接:

QNetworkAccessManager *manager = new QNetworkAccessManager();

// 建立到主机的安全TCP连接
QSslConfiguration sslConfig = QSslConfiguration::defaultConfiguration();
sslConfig.setProtocol(QSsl::TlsV1_2);
manager->connectToHostEncrypted("www.example.com", 443, sslConfig);

// 发起HTTPS请求
QNetworkRequest request(QUrl("https://www.example.com"));
request.setHeader(QNetworkRequest::ContentTypeHeader, "text/plain");
QNetworkReply *reply = manager->post(request, QByteArray("hello"));
connect(reply, &QNetworkReply::finished, this, [reply]() {
    // 处理响应数据
    QByteArray data = reply->readAll();
    qDebug() << "Received data:" << data;
});

delete manager;

在这个示例中,我们首先创建一个QNetworkAccessManager对象,然后使用connectToHostEncrypted()函数手动建立到主机的安全TCP连接。接着发送一个POST请求,获取QNetworkReply对象,并处理响应数据。需要注意的是,由于connectToHostEncrypted()函数需要手动建立安全TCP连接,因此必须在发起HTTPS请求之前,确保安全TCP连接已经成功建立。如果安全TCP连接未能成功建立,则可能导致HTTPS请求失败或超时。另外,如果使用需要peerName参数的函数,需要提供正确的服务器证书名称进行验证,否则将无法建立安全连接。

3.8 cookieJar

QNetworkCookieJar * cookieJar() const
QNetworkAccessManager::cookieJar()是一个函数,用于返回QNetworkAccessManager正在使用的cookie jar对象。Cookie jar用于存储和管理QNetworkAccessManager处理的所有HTTP cookies。

HTTP cookie是服务器在客户端存储的一小段文本信息,用于跟踪用户会话和识别用户。QNetworkAccessManager默认会自动管理HTTP cookie,包括从服务器接收cookie和在后续请求中发送cookie。可以通过设置QNetworkAccessManager的cookie jar对象来管理HTTP cookie,以便在多个请求之间共享cookie信息。

void QNetworkAccessManager::setCookieJar(QNetworkCookieJar *cookieJar)
QNetworkAccessManager::setCookieJar()是一个函数,用于设置QNetworkAccessManager正在使用的cookie jar对象。Cookie jar用于存储和管理QNetworkAccessManager处理的所有HTTP cookies。

HTTP cookie是服务器在客户端存储的一小段文本信息,用于跟踪用户会话和识别用户。QNetworkAccessManager默认会自动管理HTTP cookie,包括从服务器接收cookie和在后续请求中发送cookie。可以通过设置QNetworkAccessManager的cookie jar对象来管理HTTP cookie,以便在多个请求之间共享cookie信息。

以下是一个示例代码,展示了如何使用QNetworkAccessManager::setCookieJar()函数设置cookie jar对象:

QNetworkAccessManager *manager = new QNetworkAccessManager();

// 设置cookie jar
QNetworkCookieJar *cookieJar = new MyCookieJar();
manager->setCookieJar(cookieJar);

// 发起HTTP请求
QNetworkRequest request(QUrl("http://www.example.com"));
QNetworkReply *reply = manager->get(request);
connect(reply, &QNetworkReply::finished, this, [reply]() {
    // 处理响应数据
    QByteArray data = reply->readAll();
    qDebug() << "Received data:" << data;
});

delete manager;

在这个示例中,我们首先创建一个QNetworkAccessManager对象,然后使用setCookieJar()函数设置cookie jar对象为一个自定义的MyCookieJar对象。接着,我们发送一个GET请求,获取QNetworkReply对象,并处理响应数据。需要注意的是,在实际使用中,如果需要对cookie进行更复杂的管理,可以实现自己的QNetworkCookieJar子类,并重写QNetworkCookieJar::cookiesForUrl()和QNetworkCookieJar::setCookiesFromUrl()函数,以便实现自己的安全策略。

3.9 deleteResource

QNetworkReply *QNetworkAccessManager::deleteResource(const QNetworkRequest &request)
QNetworkAccessManager::deleteResource()是一个函数,用于发送一个HTTP DELETE请求,删除由request标识的URL对应的资源。该函数只能用于HTTP协议。
HTTP DELETE请求用于请求服务器删除指定URL对应的资源。使用QNetworkAccessManager的deleteResource()函数可以方便地向服务器发送DELETE请求。

3.10 enableStrictTransportSecurityStore

void QNetworkAccessManager::enableStrictTransportSecurityStore(bool enabled, const QString &storeDir = QString())
QNetworkAccessManager::enableStrictTransportSecurityStore()是一个函数,用于启用或禁用内部的HSTS缓存,并将HSTS策略写入持久化存储。如果启用了持久化存储,storeDir参数指定了持久化存储的路径。如果storeDir参数为空字符串,则存储路径默认为QStandardPaths::CacheLocation,即缓存目录。如果没有可写的缓存目录,并且storeDir为空字符串,则存储路径将在程序的工作目录中。

需要注意的是,如果启用持久化存储,QNetworkAccessManager会将HSTS策略写入磁盘,并从磁盘读取缓存中的策略。在启用持久化存储之前,如果缓存中已经包含了一些HSTS策略,则这些策略将会被保留在缓存中,并且缓存中的策略会覆盖磁盘中的策略。因此,在启用持久化存储之前,应该清空缓存。另外,如果缓存和持久化存储中都包含了相同的主机名和HSTS策略,缓存中的策略将被认为是最新的,并覆盖持久化存储中的策略。

3.11 get

QNetworkReply *QNetworkAccessManager::get(const QNetworkRequest &request)
QNetworkAccessManager::get()是一个函数,用于发送一个HTTP GET请求,并返回一个新的QNetworkReply对象,用于读取响应数据。在获取到新数据时,QNetworkReply对象会发出readyRead()信号。

HTTP GET请求用于请求服务器获取指定URL对应的资源。使用QNetworkAccessManager的get()函数可以方便地向服务器发送GET请求,并读取响应数据。

QNetworkAccessManager *manager = new QNetworkAccessManager();

// 发送GET请求
QUrl url("http://www.example.com");
QNetworkRequest request(url);
QNetworkReply *reply = manager->get(request);
connect(reply, &QNetworkReply::finished, this, [reply]() {
    // 处理响应数据
    QByteArray data = reply->readAll();
    qDebug() << "Received data:" << data;
});

delete manager;

3.12 head

QNetworkReply *QNetworkAccessManager::head(const QNetworkRequest &request)
QNetworkAccessManager::head()是一个函数,用于发送一个HTTP HEAD请求,获取与请求相关的网络头,并返回一个新的QNetworkReply对象,用于包含这些头。

HTTP HEAD请求类似于HTTP GET请求,但是只返回与请求相关的HTTP头信息,而不返回实际的资源内容。通常,HTTP HEAD请求用于获取资源的元数据或检查资源是否存在,而不需要实际下载资源内容。

QNetworkAccessManager *manager = new QNetworkAccessManager();

// 发送HEAD请求
QUrl url("http://www.example.com");
QNetworkRequest request(url);
QNetworkReply *reply = manager->head(request);
connect(reply, &QNetworkReply::finished, this, [reply]() {
    // 处理响应头数据
    QVariant statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute);
    QVariant contentLength = reply->header(QNetworkRequest::ContentLengthHeader);
    qDebug() << "Status code:" << statusCode.toInt();
    qDebug() << "Content length:" << contentLength.toInt();
});

delete manager;

3.13 isStrictTransportSecurityEnabled

bool QNetworkAccessManager::isStrictTransportSecurityEnabled() const
QNetworkAccessManager::isStrictTransportSecurityEnabled()是一个函数,用于判断HTTP Strict Transport Security (HSTS)是否已启用。如果已启用,返回true;否则返回false。默认情况下,HSTS是禁用的。

HTTP Strict Transport Security (HSTS)是一种安全机制,用于保护Web应用程序免受SSL剥离攻击和会话劫持攻击。当客户端和服务器首次建立HTTPS连接时,服务器可以向客户端发送HSTS响应头,要求客户端在接下来的一段时间内(例如6个月)始终使用HTTPS访问该站点。在HSTS生命周期内,如果客户端尝试使用HTTP连接到该站点,浏览器会自动将请求重定向到HTTPS。

3.14 isStrictTransportSecurityStoreEnabled

bool QNetworkAccessManager::isStrictTransportSecurityStoreEnabled() const
QNetworkAccessManager::isStrictTransportSecurityStoreEnabled()是一个函数,用于判断HTTP Strict Transport Security (HSTS)缓存是否已启用持久化存储。如果已启用,返回true;否则返回false。

3.15 post

QNetworkReply * post(const QNetworkRequest &request, QIODevice *data)
QNetworkReply * post(const QNetworkRequest &request, const QByteArray &data)
QNetworkReply * post(const QNetworkRequest &request, QHttpMultiPart *multiPart)

第一种重载形式中,data参数是一个QIODevice对象,可以用于发送二进制数据、文件数据等。下面是一个示例代码:

QNetworkAccessManager *manager = new QNetworkAccessManager();
QNetworkRequest request(QUrl("http://www.example.com/upload"));

QFile *file = new QFile("test.txt");
file->open(QIODevice::ReadOnly);

QNetworkReply *reply = manager->post(request, file);
file->setParent(reply); // 所有者设为reply,以便reply析构时能够关闭文件

// 处理reply的数据读取等操作

delete manager;

在这个示例中,我们首先创建一个QNetworkAccessManager对象和一个QNetworkRequest对象,然后创建一个QFile对象,并用open()函数打开文件。最后,我们使用QNetworkAccessManager的post()函数发送文件内容,并将文件对象设置为QNetworkReply对象的子对象。在reply被析构时,文件对象也会被自动关闭。

第二种重载形式中,data参数是一个QByteArray对象,可以用于发送纯文本数据、JSON数据等。下面是一个示例代码:

QNetworkAccessManager *manager = new QNetworkAccessManager();
QNetworkRequest request(QUrl("http://www.example.com/api"));

QByteArray postData;
postData.append("username=johndoe&password=secret");

QNetworkReply *reply = manager->post(request, postData);

// 处理reply的数据读取等操作

delete manager;

在这个示例中,我们首先创建一个QNetworkAccessManager对象和一个QNetworkRequest对象,然后创建一个QByteArray对象,并将POST数据写入该对象。最后,我们使用QNetworkAccessManager的post()函数发送POST请求,并处理reply对象的数据读取等操作。

第三种重载形式中,multiPart参数是一个QHttpMultiPart对象,可以用于发送文件、表单数据等。QHttpMultiPart是一个较为复杂的对象,可以包含多个QHttpPart对象。以下是一个示例代码:

QNetworkAccessManager *manager = new QNetworkAccessManager();
QNetworkRequest request(QUrl("http://www.example.com/upload"));

QHttpMultiPart *multiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType);
QHttpPart textPart;
textPart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"username\""));
textPart.setBody("johndoe");

QHttpPart filePart;
filePart.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("image/jpeg"));
filePart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"file\"; filename=\"test.jpg\""));

QFile *file = new QFile("test.jpg");
file->open(QIODevice::ReadOnly);
filePart.setBodyDevice(file);
file->setParent(multiPart); // 所有者设为multiPart,以便multiPart析构时能够关闭文件

multiPart->append(textPart);
multiPart->append(filePart);

QNetworkReply *reply = manager->post(request, multiPart);
multiPart->setParent(reply); // 所有者设为reply,以便reply析构时能够删除multiPart

// 处理reply的数据读取等操作

delete manager;

在这个示例中,我们首先创建一个QNetworkAccessManager对象和一个QNetworkRequest对象,然后创建一个QHttpMultiPart对象,并创建两个QHttpPart对象用于发送纯文本数据和文件数据。最后,我们使用QNetworkAccessManager的post()函数发送POST请求,并将QHttpMultiPart对象设置为QNetworkReply对象的子对象。在reply被析构时,QHttpMultiPart对象也会被自动删除。

3.16 proxy

QNetworkProxy proxy() const
该函数返回QNetworkAccessManager对象的代理服务器配置。如果QNetworkAccessManager对象没有设置代理服务器,则返回一个空的QNetworkProxy对象。

3.17 proxyFactory

QNetworkProxyFactory * proxyFactory() const
该函数返回QNetworkAccessManager对象的代理工厂。代理工厂用于创建QNetworkProxy对象,以便QNetworkAccessManager对象可以使用代理服务器转发网络请求。如果QNetworkAccessManager对象没有设置代理工厂,则返回一个空的QNetworkProxyFactory对象。

3.18 put

QNetworkReply * put(const QNetworkRequest &request, QIODevice *data)
QNetworkReply * put(const QNetworkRequest &request, const QByteArray &data)
QNetworkReply * put(const QNetworkRequest &request, QHttpMultiPart *multiPart)

第一种重载形式中,data参数是一个QIODevice对象,可以用于发送二进制数据、文件数据等。下面是一个示例代码:

QNetworkAccessManager *manager = new QNetworkAccessManager();
QNetworkRequest request(QUrl("http://www.example.com/upload"));

QFile *file = new QFile("test.txt");
file->open(QIODevice::ReadOnly);

QNetworkReply *reply = manager->put(request, file);
file->setParent(reply); // 所有者设为reply,以便reply析构时能够关闭文件

// 处理reply的数据读取等操作

delete manager;

在这个示例中,我们首先创建一个QNetworkAccessManager对象和一个QNetworkRequest对象,然后创建一个QFile对象,并用open()函数打开文件。最后,我们使用QNetworkAccessManager的put()函数发送文件内容,并将文件对象设置为QNetworkReply对象的子对象。在reply被析构时,文件对象也会被自动关闭。

第二种重载形式中,data参数是一个QByteArray对象,可以用于发送纯文本数据、JSON数据等。下面是一个示例代码:

QNetworkAccessManager *manager = new QNetworkAccessManager();
QNetworkRequest request(QUrl("http://www.example.com/api"));

QByteArray putData;
putData.append("username=johndoe&password=secret");

QNetworkReply *reply = manager->put(request, putData);

// 处理reply的数据读取等操作

delete manager;

在这个示例中,我们首先创建一个QNetworkAccessManager对象和一个QNetworkRequest对象,然后创建一个QByteArray对象,并将PUT数据写入该对象。最后,我们使用QNetworkAccessManager的put()函数发送PUT请求,并处理reply对象的数据读取等操作。

第三种重载形式中,multiPart参数是一个QHttpMultiPart对象,可以用于发送文件、表单数据等。QHttpMultiPart是一个较为复杂的对象,可以包含多个QHttpPart对象。以下是一个示例代码:

QNetworkAccessManager *manager = new QNetworkAccessManager();
QNetworkRequest request(QUrl("http://www.example.com/upload"));

QHttpMultiPart *multiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType);
QHttpPart textPart;
textPart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"username\""));
textPart.setBody("johndoe");

QHttpPart filePart;
filePart.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("image/jpeg"));
filePart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"file\"; filename=\"test.jpg\""));

QFile *file = new QFile("test.jpg");
file->open(QIODevice::ReadOnly);
filePart.setBodyDevice(file);
file->setParent(multiPart); // 所有者设为multiPart,以便multiPart析构时能够关闭文件

multiPart->append(textPart);
multiPart->append(filePart);

QNetworkReply *reply = manager->put(request, multiPart);
multiPart->setParent(reply); // 所有者设为reply,以便reply析构时能够删除multiPart

// 处理reply的数据读取等操作

delete manager;

3.19 redirectPolicy

QNetworkRequest::RedirectPolicy redirectPolicy() const
QNetworkRequest类中的redirectPolicy()函数可以用于获取网络请求的重定向策略。重定向是指当网络请求的URL发生变化时,服务器会向客户端返回一个重定向响应,以便客户端跳转到新的URL上。重定向策略决定了网络请求在遇到重定向响应时的行为。

该函数返回QNetworkRequest对象的重定向策略,它是一个QNetworkRequest::RedirectPolicy类型的枚举值。以下是QNetworkRequest::RedirectPolicy类型的枚举值:

  • QNetworkRequest::ManualRedirectPolicy:表示网络请求遇到重定向响应时,不会自动跳转到新的URL上,而是会发出finished()信号,由程序员决定是否进行跳转。
  • QNetworkRequest::AutoRedirectPolicy:表示网络请求遇到重定向响应时,会自动跳转到新的URL上。
  • QNetworkRequest::NoLessSafeRedirectPolicy:表示网络请求遇到重定向响应时,只会跳转到比原URL更安全的URL上。
  • QNetworkRequest::SameOriginRedirectPolicy:表示网络请求遇到重定向响应时,只会跳转到与原URL属于同一个域名的URL上。

以下是一个示例代码:

QNetworkAccessManager *manager = new QNetworkAccessManager();
QNetworkRequest request(QUrl("http://www.example.com/old_url"));

// 设置重定向策略为ManualRedirectPolicy
request.setRedirectPolicy(QNetworkRequest::ManualRedirectPolicy);

QNetworkReply *reply = manager->get(request);

connect(reply, &QNetworkReply::finished, [=]() {
    if (reply->error() == QNetworkReply::NoError) {
        QUrl redirectUrl = reply->attribute(QNetworkRequest::RedirectionTargetAttribute).toUrl();
        qDebug() << "The request was redirected to" << redirectUrl;

        // 手动跳转到新的URL上
        request.setUrl(redirectUrl);
        reply = manager->get(request);
    } else {
        qDebug() << "Failed to perform the request:" << reply->errorString();
    }

    reply->deleteLater();
});

delete manager;

在这个示例中,我们首先创建一个QNetworkAccessManager对象和一个QNetworkRequest对象,并将重定向策略设置为ManualRedirectPolicy。接着,我们使用QNetworkAccessManager的get()函数发送网络请求,当请求完成时,会发出finished()信号。在信号槽函数中,我们判断请求是否成功,如果成功,则获取重定向URL,并使用QNetworkAccessManager的get()函数手动跳转到新的URL上。如果请求失败,则输出错误信息。

注意:在上述示例中,我们手动跳转到新的URL上,这可能会导致一些安全问题,因此在实际开发中应该谨慎使用ManualRedirectPolicy策略。一般情况下,我们建议使用AutoRedirectPolicy策略。

3.20 sendCustomReques

QNetworkReply * sendCustomRequest(const QNetworkRequest &request, const QByteArray &verb, QIODevice *data = nullptr)
QNetworkReply * sendCustomRequest(const QNetworkRequest &request, const QByteArray &verb, const QByteArray &data)
QNetworkReply * sendCustomRequest(const QNetworkRequest &request, const QByteArray &verb, QHttpMultiPart *multiPart)
QNetworkAccessManager类中的sendCustomRequest()函数可以用于发送自定义的网络请求,这些网络请求可以使用任意的HTTP方法(如GET、POST、PUT等)。这些自定义的请求不同于QNetworkAccessManager中提供的get()、post()、put()等函数,因为它们使用了自定义的HTTP方法,因此我们需要手动设置请求头。

3.21 setAutoDeleteReplies

void setAutoDeleteReplies(bool shouldAutoDelete)

3.22 setCache

void setCache(QAbstractNetworkCache *cache)
void setCookieJar(QNetworkCookieJar *cookieJar)
void setProxy(const QNetworkProxy &proxy)
void setProxyFactory(QNetworkProxyFactory *factory)
void setRedirectPolicy(QNetworkRequest::RedirectPolicy policy)
void setStrictTransportSecurityEnabled(bool enabled)
void setTransferTimeout(int timeout = QNetworkRequest::DefaultTransferTimeoutConstant)
QVector<QHstsPolicy> strictTransportSecurityHosts() const
QStringList supportedSchemes() const
int transferTimeout() const

4 Signals

void authenticationRequired(QNetworkReply *reply, QAuthenticator *authenticator)
void encrypted(QNetworkReply *reply)
void finished(QNetworkReply *reply)
void preSharedKeyAuthenticationRequired(QNetworkReply *reply, QSslPreSharedKeyAuthenticator *authenticator)
void proxyAuthenticationRequired(const QNetworkProxy &proxy, QAuthenticator *authenticator)
void sslErrors(QNetworkReply *reply, const QList<QSslError> &errors)

5 Protected Functions

virtual QNetworkReply * createRequest(QNetworkAccessManager::Operation op, const QNetworkRequest &originalReq, QIODevice *outgoingData = nullptr)

6 Protected Slots

QStringList supportedSchemesImplementation() const

有关QT(17)- QNetworkAccessManager的更多相关文章

  1. Qt Designer的简单使用 - 2

    在前面两节的例子中,主界面窗口的尺寸和标签控件显示的矩形区域等,都是用C++代码编写的。窗口和控件的尺寸都是预估的,控件如果多起来,那就不好估计每个控件合适的位置和大小了。用C++代码编写图形界面的问题就是不直观,因此Qt项目开发了专门的可视化图形界面编辑器——QtDesigner(Qt设计师)。通过QtDesigner就可以很方便地创建图形界面文件*.ui,然后将ui文件应用到源代码里面,做到“所见即所得”,大大方便了图形界面的设计。本节就演示一下QtDesigner的简单使用,学习拖拽控件和设置控件属性,并将ui文件应用到Qt程序代码里。使用QtDesigner设计界面在开始菜单中找到「Q

  2. 关于Qt程序打包后运行库依赖的常见问题分析及解决方法 - 2

    目录一.大致如下常见问题:(1)找不到程序所依赖的Qt库version`Qt_5'notfound(requiredby(2)CouldnotLoadtheQtplatformplugin"xcb"in""eventhoughitwasfound(3)打包到在不同的linux系统下,或者打包到高版本的相同系统下,运行程序时,直接提示段错误即segmentationfault,或者Illegalinstruction(coredumped)非法指令(4)ldd应用程序或者库,查看运行所依赖的库时,直接报段错误二.问题逐个分析,得出解决方法:(1)找不到程序所依赖的Qt库version`Qt_5'

  3. ruby - 无法激活 susy-2.1.1,因为 sass-3.2.17 与 sass 冲突 (~> 3.3.0) - 2

    我已经安装了最新版本的compass、sass和susy。但我仍然收到此错误:Unabletoactivatesusy-2.1.1,becausesass-3.2.17conflictswithsass(~>3.3.0)有人知道这个Ruby是如何工作的吗?这是我安装的gem的列表:***LOCALGEMS***CFPropertyList(2.2.0)chunky_png(1.3.0)compass(0.12.4)compass-core(1.0.0.alpha.19)compass-import-once(1.0.4)compass-rails(1.1.3)fssm(0.2.10)l

  4. ruby - Fedora 17 上的 Heroku Toolbelt - 2

    我正在尝试执行教程的heroku设置部分http://ruby.railstutorial.org/.但是在https://toolbelt.heroku.com/,我注意到Fedora没有.rpm,所以我尝试分别安装Foreman和HerokuCLI。Foreman和Git安装正常,但我在使用HerokuCLI时遇到问题。当我尝试做的时候:$yuminstallrubygem-heroku然后简单地做$heroku我得到错误:/usr/share/rubygems/rubygems/dependency.rb:247:in`to_specs':Couldnotfindheroku(>

  5. Qt样式表之 QSS 语法介绍;QLineEdit、 - 2

     内容来自Qt样式表之QSS语法介绍-3YL的博客Qt样式表是一个可以自定义部件外观的十分强大的机制,可以用来美化部件。Qt样式表的概念、术语和语法都受到了HTML的层叠样式表(CascadingStyleSheets, CSS教程)的启发,不过与CSS不同的是,Qt样式表应用于部件的世界。类型选择器QPushButton匹配QPushButton及其子类的实例ID选择器QPushButton#okButton匹配所有objectName为okButton的QPushButton实例。 CSS常用样式1CSS文字属性注:px:相对长度单位,像素(Pixel)。pt:绝对长度单位,点(Point

  6. QT 设计一个串口调试工具,用一个工程就能轻松解决,外加虚拟串口工具模拟调试,在日常工作中可类比模块间通信,非常详细建议收藏 - 2

    QT串口调试工具第一节虚拟串口工具安装第二节QT创建一个基于QWidget的项目第三节UI界面设计第三节项目头文件widget.h第四节项目实现文件widget.cpp第五节main函数第六节编译结果重点第七节使用QT打包程序,不安装QT的电脑可使用第一节虚拟串口工具安装-----------------------------------------下载所需工具---------------------------------------------------------------------链接:https://pan.baidu.com/s/1QkT36S4EnH2HEAhZ1TZ8

  7. 嵌入式学习之QT学习----3 制作简单的QT界面(如:QQ登录界面) - 2

    1、创建一个QT工程newproject—>Application—>QtWidgetsApplication—>choose…(注意不要有中文路径)填写名称(我写的名称为class2)和创建路径(D:\qt\qt_demo\class2)—>填写类名,这里基类要选择“QWidget”,这样一个QT工程就创建好啦。qt的移植性非常强,一套代码我们不用修改太多,直接通用所有的平台。说明:QMainWindow:主窗口类,主窗口具有主菜单栏、工具栏和状态栏,类似于一般的应用程序的主窗口。QWidget:它是所有具有可视界面的基类,选择QWidget创建的界面对各种界面组件都可以支持。QDialog

  8. ruby - QtRuby 可以与 Qt 5 一起使用吗? - 2

    我可以在网上找到关于QtRuby的所有信息使用Qt4,但Qt的当前版本是5。这仅仅是文档跟不上现实的问题,而Qt5可以与QtRuby一起正常工作吗?如果您断言情况确实如此(Qt5不受支持),那么请用证据支持您的断言。 最佳答案 QtRubyQtruby和korundum已经多年没有维护了。要获得qtruby的维护版本,请将qtbindings安装为ruby​​gem。Qtbindings主页:https://github.com/ryanmelt/qtbindings/另见https://github.com/ryanmelt/qt

  9. ruby - 如何让 Qt4 在 Windows 7 上运行 ruby​​ 1.9.2? - 2

    总结我正在编写一个使用Qt4作为其GUI的Ruby1.9.2应用程序,我想在Linux、OSX和Windows上分发它。我的应用程序在除Windows764位机器外的所有设备上运行良好。有Win7+Qt4+1.8.7的工作示例,但显然不是Win7+Qt4+1.9.2。Ruby-Qt绑定(bind)有两个gem,qtbindings和qtruby4(有时称为qt4-qtruby),但我还没有看到它们都在Win7上运行Ruby1.9.2。qtruby4的问题ThisarticlefromOctober2008及其updatedversionfromJune2011作为一个很好的起点,但我与

  10. javascript - Qt QML 中疯狂字符串数字比较的解决方法 - 2

    这是Qt(LTS5.6.2)QMLJavaScript实现中疯狂的字符串与数字比较:console.log("240000000000"=="3776798720");console.log("240000000000"==="3776798720");console.log("240000000000"==="3776798721");输出是:truetruefalse看起来字符串被解释为(u)int32并且丢失了高字节:240000000000==0x37E11D60003776798720==0xE11D6000此错误也会影响对象:varg={};varh="2400000000

随机推荐