我在使用 Qt 应用程序时遇到一些问题;特别是 QNetworkAccessManager 类。我正在尝试使用 QNetworkAccessManager 的 post() 方法执行二进制文件的简单 HTTP 上传。文档指出我可以为 post() 提供一个指向 QIODevice 的指针,并且该类将传输在 QIODevice 中找到的数据。这表明我应该能够为 post() 提供一个指向 QFile 的指针。例如:
QFile compressedFile("temp");
compressedFile.open(QIODevice::ReadOnly);
netManager.post(QNetworkRequest(QUrl("http://mywebsite.com/upload") ), &compressedFile);
在我正在开发的 Windows 系统上似乎发生的情况是我的 Qt 应用程序从 QFile 推送数据,但随后没有完成请求;它似乎坐在那里等待文件中显示更多数据。在我手动终止应用程序之前,发布请求不会“关闭”,此时整个文件会显示在我的服务器端。
从一些调试和研究来看,我认为发生这种情况是因为 QFile 的 read() 操作在到达文件末尾时不会返回 -1。我认为 QNetworkAccessManager 正在尝试从 QIODevice 读取数据,直到它从 read() 获得 -1,此时它假设没有更多数据并关闭请求。如果它不断从 read() 中获得零的返回码,则 QNetworkAccessManager 假设可能有更多数据传入,因此它会继续等待该假设数据。
我已经通过一些测试代码确认,在读取到文件末尾后,QFile 的 read() 操作仅返回零。这似乎与 QNetworkAccessManager 的 post() 方法期望 QIODevice 的行为方式不兼容。我的问题是:
- QFile 在 Windows 下的工作方式是否存在某种限制?
- 我是否应该使用 QFile 或 QNetworkAccessManager 通过 post() 推送文件?
- 这根本不起作用吗?我是否必须找到其他方法来上传我的文件?
任何建议或提示将不胜感激。
Update:事实证明,我遇到了两个不同的问题:一个在客户端,一个在服务器端。在客户端,我必须确保我的 QFile 对象在网络事务期间保持不变。 QNetworkAccessManager 的 post() 方法立即返回,但实际上并没有立即完成。您需要将一个槽附加到 QNetworkAccessManager 的 finish() 信号,以确定 POST 何时实际完成。就我而言,很容易将 QFile 或多或少地永久保留,但我还在 finish() 信号上附加了一个槽,以便检查来自服务器的错误响应。
我将信号附加到插槽,如下所示:
connect(&netManager, SIGNAL(finished(QNetworkReply*) ), this, SLOT(postFinished(QNetworkReply*) ) );
当发送我的文件时,我写了这样的邮政编码(请注意,压缩文件是我的类的成员,因此在此代码之后不会超出范围):
compressedFile.open(QIODevice::ReadOnly);
netManager.post(QNetworkRequest(QUrl(httpDestination.getCString() ) ), &compressedFile);
来自 QNetworkAccessManager 的 finish(QNetworkReply*) 信号触发我的 postFinished(QNetworkReply*) 方法。发生这种情况时,我可以安全地关闭compressedFile并删除compressedFile表示的数据文件。出于调试目的,我还添加了一些 printf() 语句来确认事务已完成:
void CL_QtLogCompressor::postFinished(QNetworkReply* reply)
{
QByteArray response = reply->readAll();
printf("response: %s\n", response.data() );
printf("reply error %d\n", reply->error() );
reply->deleteLater();
compressedFile.close();
compressedFile.remove();
}
由于compressedFile不会立即关闭并且不会超出范围,因此QNetworkAccessManager能够花费尽可能多的时间来传输我的文件。最终交易完成并且我的 postFinished() 方法被调用。
我的另一个问题(这也导致了我所看到的事务从未完成的行为)是我的 Web 服务器的 Python 代码没有正确处理 POST,但这超出了我最初的 Qt 问题的范围。