我在Qt應用程序中遇到了一些麻煩;特別是與QNetworkAccessManager類。我正在嘗試使用QNetworkAccessManager的post()方法執行二進制文件的簡單HTTP上載。該文檔聲明我可以給QIODevice指向post(),並且該類將傳輸在QIODevice中找到的數據。這表明我應該能夠給post()一個指向QFile的指針。例如:使用QNetworkAccessManager的post()方法上傳文件
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()操作只返回0。這似乎與QNetworkAccessManager的post()方法期望QIODevice行爲的方式不兼容。我的問題是:
- 這是QFile在Windows下工作的方式的某種限制?
- 是否有一些其他方式我應該使用QFile或QNetworkAccessManager通過post()推送文件?
- 這是不會工作的,我必須找到其他方式來上傳我的文件?
任何建議或提示,將不勝感激。
更新:事實證明,我有兩個不同的問題:一個在客戶端,一個在服務器端。在客戶端,我必須確保我的QFile對象在網絡事務期間保持閒置狀態。 QNetworkAccessManager的post()方法立即返回,但實際上並未立即完成。您需要將插槽附加到QNetworkAccessManager的finished()信號以確定POST何時實際完成。在我的情況下,很容易使QFile幾乎永久保持不變,但我還爲完成的()信號附加了一個插槽以檢查來自服務器的錯誤響應。
我重視的信號,這樣的槽:
connect(&netManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(postFinished(QNetworkReply*)));
當是時候把我的文件,我寫的帖子這樣的代碼(注意,compressedFile是我班的一員,也是如此不出門的範圍這個代碼後):
compressedFile.open(QIODevice::ReadOnly);
netManager.post(QNetworkRequest(QUrl(httpDestination.getCString())), &compressedFile);
從QNetworkAccessManager成品(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問題的範圍。
爲了簡化內存管理開銷,您可以使QFile實例成爲QNetworkRequest對象的子對象,並且在請求對象被刪除時它將被自動刪除。 – VestniK 2010-05-11 08:47:16
哦,很好的電話。我會編輯以反映這一點。 – 2010-05-11 12:49:19
除...關閉外,QNetworkRequest不是QObject。但是,答覆是。 – 2010-05-11 12:59:16