QHttp in eigener classe / signal probleme

Alles rund um die Programmierung mit Qt
Antworten
pdk
Beiträge: 6
Registriert: 9. April 2006 19:55

QHttp in eigener classe / signal probleme

Beitrag von pdk »

Hallo Alle,

ich habe ein Problem mit einem Downloadmanager den ich z.Z. schreibe.

Ich habe mir an Hand des HTTP-Examples eine "downloader Klasse" geschrieben.

In meinem Hauptprogram verknüpfe ich ein Signal aus dieser mit meinem Hauptprogram.

Mein Problem ist nun das ich egal wo ich das Signal in meinem Fall (downloadDone(QString)) auslöse, der Download eigentlich noch garnicht fertig ist.
D.h. Löse ich am Ende von QHttp::requestFinished aus oder von QHttp::done oder frage zwischendurch den QHttp::stateChanged nach dem Wert null ab alles wird schon ausgelöst bevor die Datei fertig geladen ist.

Downloader Klasse:

Code: Alles auswählen

#include <QHttp>
#include <QFile>
#include <QFileInfo>
#include <QHttpResponseHeader>
#include <QUrl>
#include <QObject>
#include <QMessageBox>

#include "dler.h"

downLoader::downLoader(QObject *parent) : QObject(parent) {
	http = new QHttp;

	connect(http, SIGNAL(requestFinished(int, bool)),
                this, SLOT(httpRequestFinished(int, bool)));
    connect(http, SIGNAL(responseHeaderReceived(const QHttpResponseHeader &)),
                this, SLOT(readResponseHeader(const QHttpResponseHeader &)));
}

void downLoader::downloadFile(QString myUrl) {
	QUrl url(myUrl);
	QFileInfo fileInfo(url.path());

	if(myUrl.indexOf("?") != -1) {
		url.setPath(myUrl.right(myUrl.size()-(myUrl.indexOf(url.host())+url.host().size())));
	}
	
	QString fileName = fileInfo.fileName();

	if (QFile::exists(fileName)) {
		return;
	}

	file = new QFile(fileName);
	if (!file->open(QIODevice::WriteOnly)) {
		delete file;
		file = 0;
		return;
	}

	http->setHost(url.host(), url.port() != -1 ? url.port() : 80);
	if (!url.userName().isEmpty()) http->setUser(url.userName(), url.password());

	httpRequestAborted = false;
	httpGetId = http->get(url.path(), file);
}

void downLoader::cancelDownload() {
	httpRequestAborted = true;
	http->abort();
}

void downLoader::httpRequestFinished(int requestId, bool error) {
	if (httpRequestAborted) {
		if (file) {
			file->close();
			file->remove();
			delete file;
			file = 0;
		}

		return;
	}

	if (requestId != httpGetId) return;

	file->close();

	if (error) {
		file->remove();
	}
	delete file;
	file = 0;
	if(http->state() == 0 && !error) emit downloadDone(tr("trusted"));
	if(http->state() == 0 && error) emit downloadDone(tr("trusted but failed\nerror:%1").arg(http->errorString()));
	if(http->state() != 0 && !error) {
		http->close();
		emit downloadDone(tr("untrusted"));
	}
	if(http->state() != 0 && !error) {
		http->close();
		emit downloadDone(tr("untrusted and failed\nerror:%1").arg(http->errorString()));
	}
}

void downLoader::readResponseHeader(const QHttpResponseHeader &responseHeader) {
	if (responseHeader.statusCode() != 200) {
		httpRequestAborted = true;
		http->abort();
	}
}
Downlaoder Header:

Code: Alles auswählen

#ifndef DLER_H
#define DLER_H

#include <QObject>

class QHttp;
class QFile;
class QHttpResponseHeader;

//Downloader object
class downLoader : public QObject {

	Q_OBJECT

    public:
        downLoader(QObject *parent = 0);
		void downloadFile(QString myUrl);
		
	signals:
		void downloadDone(QString checkType);
		
    private slots:
		void cancelDownload();
        void httpRequestFinished(int requestId, bool error);
        void readResponseHeader(const QHttpResponseHeader &responseHeader);
	
    private:
		QHttp *http;
		QFile *file;
		int httpGetId;
		bool httpRequestAborted;
};

#endif
Entsprechender Abschnitt in der Hauptklasse:

Code: Alles auswählen

void MainWin::load_sites(QString lastCheck) {
	if(act_site > 0) logger(tr("Site nr. %1 done with: %2").arg(act_site-1).arg(lastCheck));
	logger(tr("Downloading site nr. %1").arg(act_site+1));
	if(act_site > site_list.size()) return;
	connect(siteLoader, SIGNAL(downloadDone(QString)), this, SLOT(load_sites(QString)));
	siteLoader->downloadFile(site_list[act_site].getUrl());
	act_site++;
}
Ich vermute mal das es damit zusammenhängt das die SocketConnection die in QHttp gestarted wird threaded ist.

Vielen Dank im Vorraus!
Saiyaman
Beiträge: 111
Registriert: 20. Mai 2005 13:52

Beitrag von Saiyaman »

Quelle: http://doc.trolltech.com/4.1/qhttp.html
For example, if you have the following sequence of requests

http->setHost("www.foo.bar"); // id == 1
http->get("/index.html"); // id == 2
http->post("register.html", data); // id == 3

and the get() request fails because the host lookup fails, then the post() request is never executed and the signals would look like this:

requestStarted(1)
requestFinished(1, false)

requestStarted(2)
stateChanged(HostLookup)
requestFinished(2, true)

done(true)

stateChanged(Unconnected)
Merkst? :) Es muss im Endeffekt auf done() gewartet werden. Das geht aber auch nur, wenn du die Connection machst, nachdem direkt nachdem der Download gestartet ist, denn sonst ist er ja schon vorher mit dem Abarbeiten anderer Befehle "done". ;)

MfG
pdk
Beiträge: 6
Registriert: 9. April 2006 19:55

Beitrag von pdk »

Hi,

verstanden und umgesetzt ;) Funktioniert jetzt sehr schön!

Vielen Dank und bis denne!
Antworten