我在使用 Qt 应用程序时遇到了一些问题;特别是 QNetworkAccessManager 类。我正在尝试使用 QNetworkAccessManager 的 post() 方法对二进制文件执行简单的 HTTP 上传。文档说明我可以将指向 QIODevice 的指针指向 post(),并且该类将传输在 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() 推送文件吗?
- 这根本不起作用,我是否必须找到其他方法来上传我的文件?
任何建议或提示将不胜感激。
更新:事实证明我有两个不同的问题:一个在客户端,一个在服务器端。在客户端,我必须确保我的 QFile 对象在网络事务期间一直存在。QNetworkAccessManager 的 post() 方法会立即返回,但实际上并没有立即完成。您需要在 QNetworkAccessManager 的 finished() 信号上附加一个插槽,以确定 POST 何时实际完成。在我的情况下,将 QFile 或多或少永久地保持在周围很容易,但我还在finished() 信号上附加了一个插槽,以检查来自服务器的错误响应。
我将信号连接到插槽,如下所示:
connect(&netManager, SIGNAL(finished(QNetworkReply*) ), this, SLOT(postFinished(QNetworkReply*) ) );
当是时候发送我的文件时,我写了这样的帖子代码(请注意,compressedFile 是我的类的成员,因此在此代码之后不会超出范围):
compressedFile.open(QIODevice::ReadOnly);
netManager.post(QNetworkRequest(QUrl(httpDestination.getCString() ) ), &compressedFile);
来自 QNetworkAccessManager 的 finished(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 问题的范围。