Название: Загрузка файлов
Отправлено: CrossScofield от Февраль 20, 2013, 01:28
Всем доброй ночи. Прошу помощи. Создал я класс для загрузки файлов, на основе стандартного примера http. Но есть одна проблема. После того как я послал команду загрузить файл, я сразу же начинаю его обрабатывать, но файл загружается позже, как будто процесс загрузки работает в отдельном потоке. Как сделать так что бы программа застывала пока загружается файл? Вот код класса: #include "download.h" #include "ui_authenticationdialog.h" download::download(QWidget *parent) : QObject() { g_isComplete=false; connect(&qnam, SIGNAL(authenticationRequired(QNetworkReply*,QAuthenticator*)), this, SLOT(slotAuthenticationRequired(QNetworkReply*,QAuthenticator*))); } void download::sslErrors(QNetworkReply*,const QList<QSslError> &errors) { QString errorString; foreach (const QSslError &error, errors) { if (!errorString.isEmpty()) errorString += ", "; errorString += error.errorString(); }
if (QMessageBox::warning(0, tr("HTTP"), tr("One or more SSL errors has occurred: %1").arg(errorString), QMessageBox::Ignore | QMessageBox::Abort) == QMessageBox::Ignore) { reply->ignoreSslErrors(); } } void download::setInfo(QUrl query, QUrl urlAdress, QString newName){ queryString = query.toString(); url = urlAdress; fileName = newName; } bool download::isComplete(){ return g_isComplete; }
void download::httpFinished() { file->flush(); file->close(); QVariant redirectionTarget = reply->attribute(QNetworkRequest::RedirectionTargetAttribute); if (reply->error()) { file->remove(); } else if (!redirectionTarget.isNull()) { QUrl newUrl = url.resolved(redirectionTarget.toUrl()); if (QMessageBox::question(0, tr("HTTP"), tr("Redirect to %1 ?").arg(newUrl.toString()), QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) { url = newUrl; reply->deleteLater(); file->open(QIODevice::WriteOnly); file->resize(0); startRequest(url); return; } } else { //file->close(); }
reply->deleteLater(); reply = 0; delete file; file = 0; g_isComplete=true; }
void download::startRequest(QUrl url) { QNetworkRequest request(url); QByteArray data; QList<QNetworkCookie> cookies; cookies.append(QNetworkCookie("PHPSESSID", "a0be8t0253m4lvo5hlv20j2ns5")); request.setHeader(QNetworkRequest::ContentTypeHeader,"application/x-www-form-urlencoded"); request.setHeader(QNetworkRequest::CookieHeader, QVariant::fromValue(cookies)); data = queryString.toAscii();
reply = qnam.post(request,data);
connect(reply, SIGNAL(finished()), this, SLOT(httpFinished())); connect(reply, SIGNAL(readyRead()), this, SLOT(httpReadyRead()));
}
void download::slotAuthenticationRequired(QNetworkReply*,QAuthenticator *authenticator) { QDialog dlg; Ui::Dialog ui; ui.setupUi(&dlg); dlg.adjustSize(); ui.siteDescription->setText(tr("%1 at %2").arg(authenticator->realm()).arg(url.host()));
// Did the URL have information? Fill the UI // this is only relevant if the URL-supplied credentials were wrong
} void download::httpReadyRead() { // this slot gets called every time the QNetworkReply has new data. // We read all of its new data and write it into the file. // That way we use less RAM than when reading it at the finished() // signal of the QNetworkReply if (file) file->write(reply->readAll()); } void download::startDownload(){ g_isComplete=false; if(fileName.isEmpty() || fileName.isNull() || url.isEmpty() || (!url.isValid())){ QMessageBox::critical(0,"Error","Name of file or URL is empty or incorrect."); return; } file = new QFile(fileName); if (!file->open(QIODevice::WriteOnly)) { QMessageBox::information(0, tr("HTTP"), tr("Unable to save the file %1: %2.") .arg(fileName).arg(file->errorString())); delete file; file = 0; return; } startRequest(url);
}
Название: Re: Загрузка файлов
Отправлено: Alex Custov от Февраль 20, 2013, 02:10
Крутить локальный QEventLoop. Но это практика порочная. Нужно использовать событийную систему, продолжая обработку загруженных данных уже в слоте по сигналу finished(), не замораживая основную нить.
Название: Re: Загрузка файлов
Отправлено: CrossScofield от Февраль 20, 2013, 12:10
Alex Custov, спасибо за ответ. Идея с eventloop мне понравилась, хоть и понимаю что это не лучшее решение, но использовать весь этот код везде где нужно загрузить файл, для меня роскошь не позволительная, так что только eventloop меня и спасет)
Название: Re: Загрузка файлов
Отправлено: GreatSnake от Февраль 20, 2013, 12:47
Крутить локальный QEventLoop. Но это практика порочная. Нужно использовать событийную систему, продолжая обработку загруженных данных уже в слоте по сигналу finished(), не замораживая основную нить.
И с чего это вдруг локальный QEventLoop стал порочным ??? И почему встроенный в QCoreApplication QEventLoop менее порочен чем локальный ???
Название: Re: Загрузка файлов
Отправлено: CrossScofield от Февраль 20, 2013, 12:55
Только что проверил QEventLoop... великолепно работает.
|