From 31050528017e11c54f408b22c92265ff6c4c4b69 Mon Sep 17 00:00:00 2001 From: Jonathan Bauer Date: Mon, 21 Mar 2011 11:48:32 +0100 Subject: and the files ^^ --- src/downloadmanager.cpp | 214 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 214 insertions(+) create mode 100644 src/downloadmanager.cpp (limited to 'src/downloadmanager.cpp') diff --git a/src/downloadmanager.cpp b/src/downloadmanager.cpp new file mode 100644 index 0000000..47582c8 --- /dev/null +++ b/src/downloadmanager.cpp @@ -0,0 +1,214 @@ +#include "downloadmanager.h" +#include "fbgui.h" + +int DownloadManager::downloaded = 0; +// ---------------------------------------------------------------------------------------- +DownloadManager::DownloadManager(){ + qxtLog->debug() << "Initializing download manager..."; + checkDownloadDirectory(); + qnam = new QNetworkAccessManager(); + dip = false; +} +// ---------------------------------------------------------------------------------------- +void DownloadManager::checkDownloadDirectory() +{ + // check if downloadPath exists, if not create it. + downloadDir = QDir(downloadPath); + if (!downloadDir.exists()){ + qxtLog->debug() << "Download directory: " << downloadDir.path() << " doesn't exist."; + QDir::current().mkdir(downloadPath); + if (downloadDir.exists()){ + qxtLog->debug() << "Created download directory: " << downloadDir.path(); + } + else { + qxtLog->debug() << "Failed to create directory: " << downloadDir.path(); + // try to save to /tmp/fbgui + downloadDir.setPath(QDir::tempPath () + "/fbgui"); + if (!downloadDir.exists()){ + QDir::current().mkdir(QDir::tempPath () + "/fbgui"); + if (!downloadDir.exists()){ + // TODO: dont exit, this shouldn't happen anyway (right?) + qxtLog->debug() << "Fatal, no target for downloads. Exiting..."; + exit(EXIT_FAILURE); + } + } + qxtLog->debug() << "Saving downloads to: " << downloadDir.absolutePath(); + } + } + else qxtLog->debug() << "Download directory: " << downloadDir.path() << " exists."; +} +// ---------------------------------------------------------------------------------------- +void DownloadManager::downloadFile(const QString& filename) +{ + QUrl fileUrl(baseURL.resolved(QUrl(filename))); + this->processDownloadRequest(fileUrl); +} +// ---------------------------------------------------------------------------------------- +void DownloadManager::downloadFile(const QUrl& fileUrl) +{ + this->processDownloadRequest(fileUrl); +} +// ---------------------------------------------------------------------------------------- +void DownloadManager::processDownloadRequest(const QUrl& url) +{ + if (url.isEmpty()){ + qxtLog->debug() << "No URL specified for download."; + return; + } + // if download in progress, enqueue file and return. + if (dip){ + dlQ.enqueue(url); + qxtLog->debug() << "Download in progress! Queued:" << url.toString() + << "(" << dlQ.size() << " in queue)"; + return; + } + // no running downloads: enqueue and start next download. + dlQ.enqueue(url); + qxtLog->debug() << "Enqueueing:" << url.toString(); + startNextDownload(); +} +// ---------------------------------------------------------------------------------------- +void DownloadManager::startNextDownload() +{ + if (dlQ.isEmpty()){ + emit downloadQueueEmpty(); + qxtLog->debug() << "Download manager ready. (1)"; + return; + } + qxtLog->debug() << "Starting next download: " << dlQ.head().toString() + << " (" << dlQ.size() - 1 << " in queue.)"; + + // dequeue next URL to download. + QUrl url = dlQ.dequeue(); + + // get filename from URL. + QString tmp = url.path(); + tmp.remove(0, tmp.lastIndexOf(QChar('/')) + 1); + + // check if filename exists on target file system + if (downloadDir.exists(tmp)){ + qxtLog->debug() << "File already exists: " << downloadDir.absoluteFilePath(tmp); + outfile.setFileName(QString(downloadDir.absolutePath() + "/" + tmp + ".\%1").arg(downloaded)); + } + else + outfile.setFileName(downloadDir.absoluteFilePath(tmp)); + qxtLog->debug() << "Saving to: " << outfile.fileName(); + + // try to open for writing + if (!outfile.open(QIODevice::WriteOnly)){ + qxtLog->debug() << "No write access to " << outfile.fileName() << " . Skipping download..."; + return; + } + + // send the request for the file + QNetworkRequest request(url); + currentDownload = qnam->get(request); + lastProgress = 0; + currentProgress = 0; + dip = true; + dltime.start(); + QObject::connect(currentDownload, SIGNAL(readyRead()), this, SLOT(downloadReady())); + QObject::connect(currentDownload, SIGNAL(metaDataChanged()), this, SLOT(processMetaInfo())); + QObject::connect(currentDownload, SIGNAL(downloadProgress(qint64, qint64)), + this, SLOT(downloadProgress(qint64, qint64))); + QObject::connect(currentDownload, SIGNAL(finished()), this, SLOT(downloadFinished())); +} +// ---------------------------------------------------------------------------------------- +// Private slots to process downloads +// ---------------------------------------------------------------------------------------- +void DownloadManager::processMetaInfo() +{ + // fetch filesize from header & filename from URL (for now) + const QByteArray cltag = "Content-Length"; + QByteArray clinfo = currentDownload->rawHeader(cltag); + QFileInfo fi(outfile); + emit downloadInfo(outfile.fileName(), clinfo.toDouble()); +} +// ---------------------------------------------------------------------------------------- +void DownloadManager::downloadReady() +{ + // data ready, save it + outfile.write(currentDownload->readAll()); +} +// ---------------------------------------------------------------------------------------- +void DownloadManager::downloadProgress(qint64 bytesIn, qint64 bytesTotal) +{ + if (bytesIn > bytesTotal) return; + // calculate current speed + double speed = bytesIn * 1000 / dltime.elapsed(); + QString unit; + if (speed < 1024) { + unit = "bytes/sec"; + } + else if (speed < 1024*1024) { + speed /= 1024; + unit = "KB/s"; + } + else { + speed /= 1024*1024; + unit = "MB/s"; + } + // update progress only if difference higher than the updateInterval setting + currentProgress = ((bytesIn * 100) / bytesTotal); + if (currentProgress - lastProgress >= updateInterval){ + lastProgress = currentProgress; + emit updateProgress(currentProgress, speed, unit); + qxtLog->debug() << "Download progress of " << currentDownload->url().toString() + << ": " << bytesIn << "/" << bytesTotal << "(" << currentProgress << "\%)"; + } + return; +} +// ---------------------------------------------------------------------------------------- +void DownloadManager::downloadFinished() +{ + // check for errors + if (currentDownload->error()){ + currentDownload->deleteLater(); + outfile.remove(); + int statusCode = currentDownload->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); + qxtLog->debug() << "Download of " << currentDownload->url().toString() + << " failed with HTTP error code: " << statusCode; + emit notify(QString("Download failed! HTTP Status Code: %1").arg(statusCode)); + } + else{ + // end download + currentDownload->deleteLater(); + outfile.close(); + downloaded++; + qxtLog->debug() << "Download of " << currentDownload->url().toString() + << " finished. (downloaded = "<< downloaded << ")"; + emit notify(QString("Successfully downloaded %1").arg(currentDownload->url().toString())); + } + dip = false; + // process next in queue + if (dlQ.isEmpty()){ + emit downloadQueueEmpty(); + qxtLog->debug() << "Download manager ready. (2)"; + return; + } + startNextDownload(); +} +/******************************************************************************************************** +* + ** dead code: Header filename fetching & renaming ** + +const QByteArray cd = "Content-Disposition"; +QByteArray cdc = currentDownload->rawHeader(cd); +int x = cdc.indexOf("filename=\"") + 10; +cdc.remove(0, x).chop(1); +if (!cdc.isEmpty()) + currentTargetFilename = cdc; +else + currentTargetFilename = QString("download.\%1").arg(downloaded); + +QString tmp = outfile.fileName(); +tmp.remove(0, tmp.lastIndexOf(QChar('/')) + 1); +qDebug() << "Trying to rename " << tmp << " to --> " << currentTargetFilename; + +if (outfile.rename(downloadPath + "/" + currentTargetFilename)) { + qxtLog->debug() << "Renamed file!"; +} +else { + qxtLog->debug() << "Failure to rename file!"; +} +*/ -- cgit v1.2.3-55-g7522