Seite 1 von 2
QFTP
Verfasst: 2. Januar 2011 18:48
von daffi
Hi Leute,
ich schreibe ein Programm, wobei ich auf einen FTP Server zugreifen muss.
Ich wollte dies am FTP von Trolltech testen. Leider funktioniert mein Code nicht.
Code: Alles auswählen
void ftp(){
QFile *file = new QFile( "test.txt" );
QFtp *ftp = new QFtp();
ftp->setTransferMode(QFtp::Active);
ftp->connectToHost("ftp.trolltech.com");
ftp->login();
ftp->cd("qt");
ftp->get("INSTALL",file,QFtp::Binary);
ftp->close();
}
Wo liegt mein Fehler? Die Text.txt existiert schon aber leider schreibt er nix rein.
Hab ich was übersehen?
Verfasst: 2. Januar 2011 19:56
von Christian81
Die Datei sollte man schon öffnen...
Das funktioniert prima bei mir:
Code: Alles auswählen
#include <QCoreApplication>
#include <QFtp>
#include <QFile>
int main(int argc, char ** argv)
{
QCoreApplication app(argc, argv);
QFile *file = new QFile( "C:\\Devel\\THP\\tmp\\test.txt" );
file->open(QIODevice::ReadWrite);
QFtp *ftp = new QFtp();
ftp->setTransferMode(QFtp::Active);
ftp->connectToHost("ftp.trolltech.com");
ftp->login();
ftp->cd("qt");
ftp->get("INSTALL",file);
ftp->close();
QObject::connect(ftp, SIGNAL(done(bool)), &app, SLOT(quit()));
int ret = app.exec();
delete ftp;
delete file;
return ret;
}
Verfasst: 2. Januar 2011 22:00
von daffi
ja das mit dem öffnen hat ich auch schon gesehen...einfach vergessen.
void DeviceRoutine::ftp(){
//Wenn FTP aus ist mache nichts
if (ui.checkBox_FTP->isChecked()==0)
return;
QFile *file = new QFile( "C:\\Users\\Daffi\\Desktop\\test.txt" );
if (file->exists())
file->remove();
file->open(QIODevice::ReadWrite);
QFtp *ftp = new QFtp();
ftp->setTransferMode(QFtp::Active);
ftp->connectToHost("ftp.trolltech.com");
ftp->login();
ftp->get("robots.txt",file);
ftp->close();
file->close();
delete ftp;
}
Das File ist immer wieder leer...was ist nun anders als in deinem Beispiel?
EDIT: Habe gerade gemerkt um die connect Aufrufe komme ich nicht drum herum.
Habs bis grade probiert,komme aber leider nicht weiter.
Ziel ist es von einer Anwendung über das klicken einer checkbox ein gesamtes Verzeichnis zu laden.
(geht es auch mit einem Buffer anstatt des Ladens jeder einzelnen Datei?)
Beispiele wären echt nett.
Das FTP Beispiel von QT finde ich sehr überladen und das mit dem Connect z.B wird nicht klar ersichtlich.
MfG
Daffi
Verfasst: 3. Januar 2011 09:29
von pfid
Also hier:
http://doc.qt.nokia.com/4.7/qftp.html#details
steht doch relativ einfach und un-überladen, wie es funktioniert. Dann kommst du sicher drauf, was das problem ist...
Verfasst: 3. Januar 2011 09:48
von Christian81
Wie soll das funktionieren wenn man die Doku liest...
The class works asynchronously, so there are no blocking functions. If an operation cannot be executed immediately, the function will still return straight away and the operation will be scheduled for later execution. The results of scheduled operations are reported via signals. This approach depends on the event loop being in operation.
Des weiteren sollte man wie beschrieben QNetworkAccessManager benutzen.
Code habe ich gezeigt. Der funktioniert!
Verfasst: 3. Januar 2011 13:13
von daffi
Also ich verstehe eines nicht.
Christians Programm geht ohne Probleme...
Ich möchte dies aber ohne das QCoreApplication machen (weil argc und argv) nicht bekannt sind.
sobald ich den Teil raus lasse geht es wieder nicht.
Verfasst: 3. Januar 2011 14:04
von upsala
Warum sollten argc und argv nicht bekannt sein?
Warum schreibst du nicht gleich, daß du keine QCoreApplication verwendest, wie soll den eine Event-Routine abgehandelt werden?
Verfasst: 3. Januar 2011 14:23
von daffi
QCoreApp ist doch eine Konsolen App, richtig?
Ich schrieb oben folgendes:
Ziel ist es von einer Anwendung über das klicken einer checkbox ein gesamtes Verzeichnis zu laden.
(geht es auch mit einem Buffer anstatt des Ladens jeder einzelnen Datei?)
CHeckBox != Konsole
Ziel ist es, wenn irgendwann jemand die Box drückt, dass
alle Dateien mit einer gewissen Endung gezogen werden.
Dazu wollte ich als Beispiel ersteinmal eine Datei ziehen.
Die Connect Funktion der Checkbox geht und verweist auf meine FTP Funktion :
Code: Alles auswählen
void DeviceRoutine::ftp(){
//Wenn FTP aus ist mache nichts
if (ui.checkBox_FTP->isChecked()==0)
return;
QFile *file = new QFile( "C:\\Users\\Daffi\\Desktop\\test.txt" );
if (file->exists())
file->remove();
file->open(QIODevice::ReadWrite);
QFtp *ftp = new QFtp();
ftp->setTransferMode(QFtp::Active);
ftp->connectToHost("ftp.trolltech.com");
ftp->login();
ftp->get("robots.txt",file);
connect(ftp, SIGNAL(done(bool)), this, SLOT(beenden()));
delete ftp;
delete file;
}
Allerdings legt er nur eine neue Datei an, der Rest wird nicht getriggert.
Die Frage ist Warum nicht bzw wie mache ich das NICHT auf KonsolenBasis.
Verfasst: 3. Januar 2011 14:39
von franzf
ARGH! Du schreibst oben
Ich möchte dies aber ohne das QCoreApplication machen (weil argc und argv) nicht bekannt sind.
Niente von wegen GUI. Und für Gui mit Qt brauchst du ein QApplication, was 1) von QCoreApplication abgeleitet ist und 2) auch argc und argv als Parameter erwartet. was bei argc und argv das Problem ist, solltest du bitte mal erklären.
Zu deinem eigentlichen Problem wurde bereits was gesagt. QFtp arbeitet asynchron, ein get() usw. stoßen eine Aktion im Hintergrund an und kehren sofort an die Stelle des Aufrufs zurück. Wenn du danach sofort dein ftp und file zerstörst, werden diese asynchronen Operationen sofort abgebrochen.
Ergo: Schau dass dein ftp und file-Objekt so lange leben, wie sie brauchen die Dateien herunter zu laden.
Und wo du in deinem Code jetzt versuchst ALLE Dateien mit einer bestimmten Endung zu holen seh ich auch nicht - du forderst explizit nur die robots.txt an.
Ich denke du solltest zu allererst C++ ordentlich lernen. (Wg. Verständnis für Objektzugehörigkeiten, Lebenszeit, Instanziierung, usw.), danach die Qt-Grundlagen. Natürlich kannst du das auch parallel zu deinem Projekt machen, aber mMn. besteht da noch etwas Nachholbedarf.
Verfasst: 3. Januar 2011 14:47
von daffi
Em ich glaub du kannst nicht lesen oder wir reden an einander vorbei!
argv und argc sind nicht in meiner Klasse bekannt. (Logisch kommen von der Main)
Da ich aber innerhalb einer Klasse den FTP Transfer durchziehen will und nicht als batch oder sonstiges wüsste ich nicht wie ich dies bewerkstellige.
Das FTp Objekt bleibt lange genug am leben! Schließlich ist es nur 1kb groß und bei Christian gehts genau so mit dem selben Code.
Und ich weis wohl genau das dies noch nicht für alle gilt,denn schließlich ist das ja auch das Ziel und nicht der Ist-Zustand....
wie ich bereits schrieb:
Dazu wollte ich als Beispiel ersteinmal eine Datei ziehen.
Verfasst: 3. Januar 2011 15:03
von franzf
daffi hat geschrieben:Das FTp Objekt bleibt lange genug am leben! Schließlich ist es nur 1kb groß und bei Christian gehts genau so mit dem selben Code.
Garantiert stirbt dein ftp-Objekt viel zu früh! Ist dir klar, wie schnell dein Rechner mit der get()-Methode durch ist, und was bei einer Verbindung mit einem entfernten FTP-Server an Zeit flöten geht? Oder willst du mir weiß machen, dass deine Internetleitung schneller ist, als die Anbindung deines RAM an die CPU (L1/2/3-Caches mal komplett weggelassen)...
Dass der Code von Christian funktioniert hat einen einfachen Grund.
Code: Alles auswählen
QObject::connect(ftp, SIGNAL(done(bool)), &app, SLOT(quit()));
int ret = app.exec();
So lange ftp nicht done() sendet, rödelt die app in der EventLoop rum (app.exec()). Sobald ftp seine Dateien gezogen hat, wird done() emittiert, der angeschlossene app.quit() aufgerufen, was die EventLoop beendet. Jetzt wird app.exec() beendet, und der Code hinter app.exec() abgearbeitet - Dazu zählt auch das delete ftp.
Eine mögliche Lösung: Macht ftp und file zu einem Member deiner Klasse, dann hast du die Objekte und deren Lebenszeit voll in der Hand!
Verfasst: 3. Januar 2011 15:09
von daffi
Ah Ok.Das war die Antwort auf die ich so etwa gewwartet habe.Jetzt ist mir schon einiges klarer.
Gut, gänge theoretisch auch eine while schleife um auf den FTP zu warten?
Verfasst: 3. Januar 2011 16:36
von franzf
daffi hat geschrieben:Gut, gänge theoretisch auch eine while schleife um auf den FTP zu warten?
Versuch es nicht. Netzwerkzugriffe sind nicht umsonst asynchron. Lass den Server hängen dann hängt auch deine Applikation. Ich würd mich nicht wundern, wenn dir auch der kurze Lock der GUI zu viel wird, und du dann frägst, wie du die Arbeit in nen neuen Thread auslagern kannst
Die asynchrone Kommunikation via SIGNAL/SLOT ist bei dem QFtp jetzt wirklich nicht schwer (aufs done warten, bingo). Und eine synchrone API ala waitForFinished() bietet dir AFAIK keine der Qt-Netzwerkklassen.
Verfasst: 3. Januar 2011 16:45
von daffi
wie kann ich dennoch in einer Unterfunktion einer klasse also eine normale memberfunktion eine QCoreApplication erstellen? Weil die brauche ich ja anscheinend...
Verfasst: 3. Januar 2011 17:13
von pfid
daffi hat geschrieben:wie kann ich dennoch in einer Unterfunktion einer klasse also eine normale memberfunktion eine QCoreApplication erstellen? Weil die brauche ich ja anscheinend...
In der Regel wird das so wie in Christians Beispiel gemacht. In deiner main-Funktion wird ein Q(Core-)Application Objekt erstellt, und mit app.exec (siehe christians Beispiel..) die Event-Loop gestartet. Zwischen erstellen der Q(Core-)Application und dem Starten der Event-Loop legst du dann dein Hauptfenster o.ä. an (siehe christians Beispiel..).
In deiner Unterfunktion deiner Klasse brauchst/sollst/darfst du keine QCoreApplication erstellen. Siehe hier:
http://doc.qt.nokia.com/4.7/gettingstartedqt.html