Ich habe Probleme mit einer Qt-Anwendung; speziell mit der QNetworkAccessManager-Klasse. Ich versuche, einen einfachen HTTP-Upload einer Binärdatei mit der Methode post() des QNetworkAccessManagers durchzuführen. Die Dokumentation besagt, dass ich einen Zeiger auf einen QIODevice für post() geben kann, und dass die Klasse die im QIODevice gefundenen Daten überträgt. Dies deutet darauf hin, dass ich post() einen Zeiger auf eine QFile geben könnte. Zum Beispiel:Hochladen einer Datei mit der Methode post() von QNetworkAccessManager
QFile compressedFile("temp");
compressedFile.open(QIODevice::ReadOnly);
netManager.post(QNetworkRequest(QUrl("http://mywebsite.com/upload")), &compressedFile);
Was auf dem Windows-System scheint zu passieren, wo ich entwickle ist, dass meine Qt-Anwendung die Daten aus dem QFile schiebt, aber dann die Anforderung nicht abgeschlossen; Es scheint dort zu sitzen und darauf zu warten, dass mehr Daten aus der Datei angezeigt werden. Die Postanforderung wird nicht "geschlossen", bis ich die Anwendung manuell beendet habe. Zu diesem Zeitpunkt wird die gesamte Datei an meinem Server angezeigt.
Aus einigen Debugging und Forschung, ich denke, das passiert, weil die Operation read() von QFile -1 nicht zurückgibt, wenn Sie das Ende der Datei erreichen. Ich denke, dass QNetworkAccessManager versucht, aus dem QIODevice zu lesen, bis es ein -1 von read() erhält, an dem es annimmt, dass keine Daten mehr vorhanden sind, und die Anforderung schließt. Wenn es von read() einen Rückgabecode von Null erhält, geht QNetworkAccessManager davon aus, dass möglicherweise mehr Daten kommen, und wartet daher auf diese hypothetischen Daten.
Ich habe mit einigen Testcode bestätigt, dass die read() - Operation von QFile nur Null zurückgibt, nachdem Sie bis zum Ende der Datei gelesen haben. Dies scheint mit der Art und Weise, wie die post() -Methode von QNetworkAccessManager erwartet, dass sich ein QIODevice verhält, nicht kompatibel zu sein. Meine Fragen sind:
- Ist dies eine Art von Einschränkung mit der Art, wie QFile unter Windows funktioniert?
- Gibt es eine andere Möglichkeit, ich sollte entweder QFile oder QNetworkAccessManager verwenden, um eine Datei per Post() zu schieben?
- Wird das überhaupt nicht funktionieren, und muss ich eine andere Möglichkeit finden, meine Datei hochzuladen?
Alle Vorschläge oder Hinweise würden geschätzt.
Update: Es stellt sich heraus, dass ich zwei verschiedene Probleme hatte: eines auf der Client-Seite und eines auf der Server-Seite. Auf der Clientseite musste ich sicherstellen, dass mein QFile-Objekt für die Dauer der Netzwerktransaktion erhalten blieb. Die Methode post() von QNetworkAccessManager wird sofort zurückgegeben, ist aber nicht sofort fertig. Sie müssen einen Slot an das fertige() Signal von QNetworkAccessManager anhängen, um festzustellen, wann der POST tatsächlich beendet ist. In meinem Fall war es einfach genug, das QFile mehr oder weniger permanent herumzuhalten, aber ich habe auch einen Slot an das fertige() Signal angehängt, um nach Fehlerantworten vom Server zu suchen.
angebracht ich das Signal an den Schlitz wie folgt aus:
connect(&netManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(postFinished(QNetworkReply*)));
Als es Zeit war meine Datei zu senden, ich die Post Code wie folgt geschrieben (beachten Sie, dass compressedFile ein Mitglied meiner Klasse ist und so tut out of scope nicht nach diesem Code gehen):
compressedFile.open(QIODevice::ReadOnly);
netManager.post(QNetworkRequest(QUrl(httpDestination.getCString())), &compressedFile);
Das fertige (QNetworkReply *) Signal von QNetworkAccessManager löst meine postFinished (QNetworkReply *) Methode. Wenn dies passiert, kann ich compressedFile sicher schließen und die Datendatei, die von compressedFile dargestellt wird, löschen.Für Debugging-Zwecke Ich habe auch ein paar printf() Aussagen zu bestätigen, dass die Transaktion abgeschlossen ist:
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();
}
Da compressedFile nicht sofort geschlossen ist und nicht aus dem Anwendungsbereich geht, die QNetworkAccessManager der Lage ist, als zu nehmen viel Zeit, wie es meine Datei übertragen möchte. Schließlich ist die Transaktion abgeschlossen und meine postFinished() -Methode wird aufgerufen.
Mein anderes Problem (das auch zu dem Verhalten beitrug, das ich sah, wo die Transaktion nie abgeschlossen wurde) war, dass der Python-Code für meinen Webserver den POST nicht richtig eingab, aber das ist außerhalb des Bereichs meiner ursprünglichen Qt-Frage .
Um den Speicherverwaltungsaufwand zu vereinfachen, können Sie die QFile-Instanz als untergeordnetes Objekt des QNetworkRequest-Objekts definieren. Sie wird automatisch gelöscht, wenn das Anforderungsobjekt gelöscht wird. – VestniK
Oh, guten Ruf. Ich werde bearbeiten, um das zu reflektieren. –
Außer ... close, QNetworkRequest ist kein QObject. Die Antwort ist jedoch. –