windows – 使用QNetworkAccessManager的post()方法上传文件
我在使用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推送数据,但是没有完成请求;它似乎坐在那里等待从文件中显示更多数据.在我手动终止应用程序之前,post请求不会“关闭”,此时整个文件显示在我的服务器端. 从一些调试和研究来看,我认为这种情况正在发生,因为当你到达文件末尾时,QFile的read()操作不会返回-1.我认为QNetworkAccessManager试图从QIODevice读取,直到它从read()获得-1,此时它假定没有更多数据并关闭请求.如果它继续从read()获得零返回码,QNetworkAccessManager假定可能有更多数据到来,因此它一直在等待该假设数据. 我已经用一些测试代码确认,在你读完文件末尾后,QFile的read()操作只返回零.这似乎与QNetworkAccessManager的post()方法期望QIODevice的行为方式不兼容.我的问题是: >这是否与QFile在Windows下的工作方式有某种限制? 任何建议或提示将不胜感激. 更新:事实证明我有两个不同的问题:一个在客户端,一个在服务器端.在客户端,我必须确保我的QFile对象在网络事务期间保持不变. QNetworkAccessManager的post()方法立即返回,但实际上并未立即完成.您需要将一个槽附加到QNetworkAccessManager的finished()信号,以确定POST何时实际完成.在我的情况下,很容易将QFile保持在或多或少永久,但我还在finish()信号上附加了一个插槽,以便检查来自服务器的错误响应. 我将信号附加到插槽中,如下所示: connect(&netManager,SIGNAL(finished(QNetworkReply*) ),this,SLOT(postFinished(QNetworkReply*) ) ); 什么时候发送我的文件,我写了这样的邮政编码(请注意,compressFile是我的类的成员,因此在此代码之后不会超出范围): compressedFile.open(QIODevice::ReadOnly); netManager.post(QNetworkRequest(QUrl(httpDestination.getCString() ) ),&compressedFile); 来自QNetworkAccessManager的完成(QNetworkReply *)信号触发我的postFinished(QNetworkReply *)方法.发生这种情况时,我可以安全地关闭compressedFile并删除co??mpressedFile表示的数据文件.出于调试目的,我还添加了一些printf()语句来确认事务已完成: void CL_QtLogCompressor::postFinished(QNetworkReply* reply) { QByteArray response = reply->readAll(); printf("response: %sn",response.data() ); printf("reply error %dn",reply->error() ); reply->deleteLater(); compressedFile.close(); compressedFile.remove(); } 由于compressedFile不会立即关闭并且不会超出范围,因此QNetworkAccessManager可以花费尽可能多的时间来传输我的文件.最终事务完成,我的postFinished()方法被调用. 我的另一个问题(这也导致我看到事务从未完成的行为)是我的Web服务器的Python代码没有正确地部署POST,但这超出了我原来的Qt问题的范围.
您正在堆栈上创建compressedFile,并将指针传递给您的QNetworkRequest(最终是您的QNetworkAccessManager).离开您所在的方法后,compressedFile就会超出范围.虽然行为未定义,但我很惊讶它并没有让你崩溃.
您需要在堆上创建QFile: QFile *compressedFile = new QFile("temp"); 您当然需要跟踪它,然后在帖子完成后将其删除,或者将其设置为QNetworkReply的子级,以便在以后销毁时将其销毁: QFile *compressedFile = new QFile("temp"); compressedFile->open(QIODevice::ReadOnly); QNetworkReply *reply = netManager.post(QNetworkRequest(QUrl("http://mywebsite.com/upload") ),compressedFile); compressedFile->setParent(reply); (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |