Improve DownloadManager.

Now we can use downloaded data directly without saving to file.
We also can disable redirection to Magnet URI handling (useful for
non-torrent files downloading).
This commit is contained in:
Vladimir Golovnev (Glassez) 2015-06-03 11:49:39 +03:00
parent 336519b7b5
commit c702a7e426
11 changed files with 45 additions and 27 deletions

View file

@ -1049,7 +1049,7 @@ bool Session::addTorrent(QString source, const AddTorrentParams &params)
if (Utils::Misc::isUrl(source)) { if (Utils::Misc::isUrl(source)) {
Logger::instance()->addMessage(tr("Downloading '%1', please wait...", "e.g: Downloading 'xxx.torrent', please wait...").arg(source)); Logger::instance()->addMessage(tr("Downloading '%1', please wait...", "e.g: Downloading 'xxx.torrent', please wait...").arg(source));
// Launch downloader // Launch downloader
Net::DownloadHandler *handler = Net::DownloadManager::instance()->downloadUrl(source, 10485760 /* 10MB */); Net::DownloadHandler *handler = Net::DownloadManager::instance()->downloadUrl(source, true, 10485760 /* 10MB */, true);
connect(handler, SIGNAL(downloadFinished(QString, QString)), this, SLOT(handleDownloadFinished(QString, QString))); connect(handler, SIGNAL(downloadFinished(QString, QString)), this, SLOT(handleDownloadFinished(QString, QString)));
connect(handler, SIGNAL(downloadFailed(QString, QString)), this, SLOT(handleDownloadFailed(QString, QString))); connect(handler, SIGNAL(downloadFailed(QString, QString)), this, SLOT(handleDownloadFailed(QString, QString)));
connect(handler, SIGNAL(redirectedToMagnet(QString, QString)), this, SLOT(handleRedirectedToMagnet(QString, QString))); connect(handler, SIGNAL(redirectedToMagnet(QString, QString)), this, SLOT(handleRedirectedToMagnet(QString, QString)));

View file

@ -46,11 +46,13 @@ static QString errorCodeToString(QNetworkReply::NetworkError status);
using namespace Net; using namespace Net;
DownloadHandler::DownloadHandler(QNetworkReply *reply, DownloadManager *manager, qint64 limit) DownloadHandler::DownloadHandler(QNetworkReply *reply, DownloadManager *manager, bool saveToFile, qint64 limit, bool handleRedirectToMagnet)
: QObject(manager) : QObject(manager)
, m_reply(reply) , m_reply(reply)
, m_manager(manager) , m_manager(manager)
, m_saveToFile(saveToFile)
, m_sizeLimit(limit) , m_sizeLimit(limit)
, m_handleRedirectToMagnet(handleRedirectToMagnet)
, m_url(reply->url().toString()) , m_url(reply->url().toString())
{ {
init(); init();
@ -88,11 +90,23 @@ void DownloadHandler::processFinishedDownload()
} }
else { else {
// Success // Success
QString filePath; QByteArray replyData = m_reply->readAll();
if (saveToFile(filePath)) if (m_reply->rawHeader("Content-Encoding") == "gzip") {
emit downloadFinished(m_url, filePath); // uncompress gzip reply
else Utils::Gzip::uncompress(replyData, replyData);
emit downloadFailed(m_url, tr("I/O Error")); }
if (m_saveToFile) {
QString filePath;
if (saveToFile(replyData, filePath))
emit downloadFinished(m_url, filePath);
else
emit downloadFailed(m_url, tr("I/O Error"));
}
else {
emit downloadFinished(m_url, replyData);
}
this->deleteLater(); this->deleteLater();
} }
} }
@ -126,7 +140,7 @@ void DownloadHandler::init()
connect(m_reply, SIGNAL(finished()), this, SLOT(processFinishedDownload())); connect(m_reply, SIGNAL(finished()), this, SLOT(processFinishedDownload()));
} }
bool DownloadHandler::saveToFile(QString &filePath) bool DownloadHandler::saveToFile(const QByteArray &replyData, QString &filePath)
{ {
QTemporaryFile *tmpfile = new QTemporaryFile; QTemporaryFile *tmpfile = new QTemporaryFile;
if (!tmpfile->open()) { if (!tmpfile->open()) {
@ -138,11 +152,6 @@ bool DownloadHandler::saveToFile(QString &filePath)
filePath = tmpfile->fileName(); filePath = tmpfile->fileName();
qDebug("Temporary filename is: %s", qPrintable(filePath)); qDebug("Temporary filename is: %s", qPrintable(filePath));
if (m_reply->isOpen() || m_reply->open(QIODevice::ReadOnly)) { if (m_reply->isOpen() || m_reply->open(QIODevice::ReadOnly)) {
QByteArray replyData = m_reply->readAll();
if (m_reply->rawHeader("Content-Encoding") == "gzip") {
// uncompress gzip reply
Utils::Gzip::uncompress(replyData, replyData);
}
tmpfile->write(replyData); tmpfile->write(replyData);
tmpfile->close(); tmpfile->close();
// XXX: tmpfile needs to be deleted on Windows before using the file // XXX: tmpfile needs to be deleted on Windows before using the file
@ -171,14 +180,20 @@ void DownloadHandler::handleRedirection(QUrl newUrl)
if (newUrlString.startsWith("magnet:", Qt::CaseInsensitive)) { if (newUrlString.startsWith("magnet:", Qt::CaseInsensitive)) {
qDebug("Magnet redirect detected."); qDebug("Magnet redirect detected.");
m_reply->abort(); m_reply->abort();
emit redirectedToMagnet(m_url, newUrlString); if (m_handleRedirectToMagnet)
emit redirectedToMagnet(m_url, newUrlString);
else
emit downloadFailed(m_url, tr("Unexpected redirect to magnet URI."));
this->deleteLater(); this->deleteLater();
} }
else { else {
DownloadHandler *tmp = m_manager->downloadUrl(newUrlString, m_sizeLimit); DownloadHandler *tmp = m_manager->downloadUrl(newUrlString, m_sizeLimit);
m_reply->deleteLater(); m_reply->deleteLater();
m_reply = tmp->m_reply; m_reply = tmp->m_reply;
m_saveToFile = tmp->m_saveToFile;
m_sizeLimit = tmp->m_sizeLimit; m_sizeLimit = tmp->m_sizeLimit;
m_handleRedirectToMagnet = tmp->m_handleRedirectToMagnet;
init(); init();
tmp->m_reply = 0; tmp->m_reply = 0;
delete tmp; delete tmp;

View file

@ -47,12 +47,13 @@ namespace Net
Q_OBJECT Q_OBJECT
public: public:
DownloadHandler(QNetworkReply *reply, DownloadManager *manager, qint64 limit = 0); DownloadHandler(QNetworkReply *reply, DownloadManager *manager, bool saveToFile = false, qint64 limit = 0, bool handleRedirectToMagnet = false);
~DownloadHandler(); ~DownloadHandler();
QString url() const; QString url() const;
signals: signals:
void downloadFinished(const QString &url, const QByteArray &data);
void downloadFinished(const QString &url, const QString &filePath); void downloadFinished(const QString &url, const QString &filePath);
void downloadFailed(const QString &url, const QString &reason); void downloadFailed(const QString &url, const QString &reason);
void redirectedToMagnet(const QString &url, const QString &magnetUri); void redirectedToMagnet(const QString &url, const QString &magnetUri);
@ -63,12 +64,14 @@ namespace Net
private: private:
void init(); void init();
bool saveToFile(QString &filePath); bool saveToFile(const QByteArray &replyData, QString &filePath);
void handleRedirection(QUrl newUrl); void handleRedirection(QUrl newUrl);
QNetworkReply *m_reply; QNetworkReply *m_reply;
DownloadManager *m_manager; DownloadManager *m_manager;
bool m_saveToFile;
qint64 m_sizeLimit; qint64 m_sizeLimit;
bool m_handleRedirectToMagnet;
QString m_url; QString m_url;
}; };
} }

View file

@ -75,7 +75,7 @@ DownloadManager *DownloadManager::instance()
return m_instance; return m_instance;
} }
DownloadHandler *DownloadManager::downloadUrl(const QString &url, qint64 limit) DownloadHandler *DownloadManager::downloadUrl(const QString &url, bool saveToFile, qint64 limit, bool handleRedirectToMagnet)
{ {
// Update proxy settings // Update proxy settings
applyProxySettings(); applyProxySettings();
@ -91,7 +91,7 @@ DownloadHandler *DownloadManager::downloadUrl(const QString &url, qint64 limit)
qDebug("Downloading %s...", request.url().toEncoded().data()); qDebug("Downloading %s...", request.url().toEncoded().data());
// accept gzip // accept gzip
request.setRawHeader("Accept-Encoding", "gzip"); request.setRawHeader("Accept-Encoding", "gzip");
return new DownloadHandler(m_networkManager.get(request), this, limit); return new DownloadHandler(m_networkManager.get(request), this, saveToFile, limit, handleRedirectToMagnet);
} }
QList<QNetworkCookie> DownloadManager::cookiesForUrl(const QString &url) const QList<QNetworkCookie> DownloadManager::cookiesForUrl(const QString &url) const

View file

@ -53,7 +53,7 @@ namespace Net
static void freeInstance(); static void freeInstance();
static DownloadManager *instance(); static DownloadManager *instance();
DownloadHandler *downloadUrl(const QString &url, qint64 limit = 0); DownloadHandler *downloadUrl(const QString &url, bool saveToFile = false, qint64 limit = 0, bool handleRedirectToMagnet = false);
QList<QNetworkCookie> cookiesForUrl(const QString &url) const; QList<QNetworkCookie> cookiesForUrl(const QString &url) const;
bool setCookiesFromUrl(const QList<QNetworkCookie> &cookieList, const QUrl &url); bool setCookiesFromUrl(const QList<QNetworkCookie> &cookieList, const QUrl &url);

View file

@ -135,7 +135,7 @@ void AddNewTorrentDialog::show(QString source, QWidget *parent)
if (Utils::Misc::isUrl(source)) { if (Utils::Misc::isUrl(source)) {
// Launch downloader // Launch downloader
Net::DownloadHandler *handler = Net::DownloadManager::instance()->downloadUrl(source, 10485760 /* 10MB */); Net::DownloadHandler *handler = Net::DownloadManager::instance()->downloadUrl(source, true, 10485760 /* 10MB */, true);
connect(handler, SIGNAL(downloadFinished(QString, QString)), dlg, SLOT(handleDownloadFinished(QString, QString))); connect(handler, SIGNAL(downloadFinished(QString, QString)), dlg, SLOT(handleDownloadFinished(QString, QString)));
connect(handler, SIGNAL(downloadFailed(QString, QString)), dlg, SLOT(handleDownloadFailed(QString, QString))); connect(handler, SIGNAL(downloadFailed(QString, QString)), dlg, SLOT(handleDownloadFailed(QString, QString)));
connect(handler, SIGNAL(redirectedToMagnet(QString, QString)), dlg, SLOT(handleRedirectedToMagnet(QString, QString))); connect(handler, SIGNAL(redirectedToMagnet(QString, QString)), dlg, SLOT(handleRedirectedToMagnet(QString, QString)));

View file

@ -1570,7 +1570,7 @@ void MainWindow::installPython()
{ {
setCursor(QCursor(Qt::WaitCursor)); setCursor(QCursor(Qt::WaitCursor));
// Download python // Download python
Net::DownloadHandler *handler = Net::DownloadManager::instance()->downloadUrl("https://www.python.org/ftp/python/3.4.3/python-3.4.3.msi"); Net::DownloadHandler *handler = Net::DownloadManager::instance()->downloadUrl("https://www.python.org/ftp/python/3.4.3/python-3.4.3.msi", true);
connect(handler, SIGNAL(downloadFinished(QString, QString)), this, SLOT(pythonDownloadSuccess(QString, QString))); connect(handler, SIGNAL(downloadFinished(QString, QString)), this, SLOT(pythonDownloadSuccess(QString, QString)));
connect(handler, SIGNAL(downloadFailed(QString, QString)), this, SLOT(pythonDownloadFailure(QString, QString))); connect(handler, SIGNAL(downloadFailed(QString, QString)), this, SLOT(pythonDownloadFailure(QString, QString)));
} }

View file

@ -59,7 +59,7 @@ QStringList TrackersAdditionDlg::newTrackers() const
void TrackersAdditionDlg::on_uTorrentListButton_clicked() void TrackersAdditionDlg::on_uTorrentListButton_clicked()
{ {
uTorrentListButton->setEnabled(false); uTorrentListButton->setEnabled(false);
Net::DownloadHandler *handler = Net::DownloadManager::instance()->downloadUrl(QString("http://www.torrentz.com/announce_%1").arg(m_torrent->hash())); Net::DownloadHandler *handler = Net::DownloadManager::instance()->downloadUrl(QString("http://www.torrentz.com/announce_%1").arg(m_torrent->hash()), true);
connect(handler, SIGNAL(downloadFinished(QString, QString)), this, SLOT(parseUTorrentList(QString, QString))); connect(handler, SIGNAL(downloadFinished(QString, QString)), this, SLOT(parseUTorrentList(QString, QString)));
connect(handler, SIGNAL(downloadFailed(QString, QString)), this, SLOT(getTrackerError(QString, QString))); connect(handler, SIGNAL(downloadFailed(QString, QString)), this, SLOT(getTrackerError(QString, QString)));
//Just to show that it takes times //Just to show that it takes times

View file

@ -66,7 +66,7 @@ RssFeed::RssFeed(RssManager* manager, RssFolder* parent, const QString& url):
connect(manager->rssParser(), SIGNAL(feedParsingFinished(QString,QString)), SLOT(handleFeedParsingFinished(QString,QString))); connect(manager->rssParser(), SIGNAL(feedParsingFinished(QString,QString)), SLOT(handleFeedParsingFinished(QString,QString)));
// Download the RSS Feed icon // Download the RSS Feed icon
Net::DownloadHandler *handler = Net::DownloadManager::instance()->downloadUrl(iconUrl()); Net::DownloadHandler *handler = Net::DownloadManager::instance()->downloadUrl(iconUrl(), true);
connect(handler, SIGNAL(downloadFinished(QString, QString)), this, SLOT(handleFinishedDownload(QString, QString))); connect(handler, SIGNAL(downloadFinished(QString, QString)), this, SLOT(handleFinishedDownload(QString, QString)));
connect(handler, SIGNAL(downloadFailed(QString, QString)), this, SLOT(handleDownloadFailure(QString, QString))); connect(handler, SIGNAL(downloadFailed(QString, QString)), this, SLOT(handleDownloadFailure(QString, QString)));
m_iconUrl = handler->url(); m_iconUrl = handler->url();
@ -167,7 +167,7 @@ bool RssFeed::refresh()
} }
m_loading = true; m_loading = true;
// Download the RSS again // Download the RSS again
Net::DownloadHandler *handler = Net::DownloadManager::instance()->downloadUrl(m_url); Net::DownloadHandler *handler = Net::DownloadManager::instance()->downloadUrl(m_url, true);
connect(handler, SIGNAL(downloadFinished(QString, QString)), this, SLOT(handleFinishedDownload(QString, QString))); connect(handler, SIGNAL(downloadFinished(QString, QString)), this, SLOT(handleFinishedDownload(QString, QString)));
connect(handler, SIGNAL(downloadFailed(QString, QString)), this, SLOT(handleDownloadFailure(QString, QString))); connect(handler, SIGNAL(downloadFailed(QString, QString)), this, SLOT(handleDownloadFailure(QString, QString)));
m_url = handler->url(); // sync URL encoding m_url = handler->url(); // sync URL encoding

View file

@ -474,7 +474,7 @@ void TrackerFiltersList::addItem(const QString &tracker, const QString &hash)
trackerItem = new QListWidgetItem(); trackerItem = new QListWidgetItem();
trackerItem->setData(Qt::DecorationRole, GuiIconProvider::instance()->getIcon("network-server")); trackerItem->setData(Qt::DecorationRole, GuiIconProvider::instance()->getIcon("network-server"));
Net::DownloadHandler *h = Net::DownloadManager::instance()->downloadUrl(QString("http://%1/favicon.ico").arg(host)); Net::DownloadHandler *h = Net::DownloadManager::instance()->downloadUrl(QString("http://%1/favicon.ico").arg(host), true);
connect(h, SIGNAL(downloadFinished(QString, QString)), this, SLOT(handleFavicoDownload(QString, QString))); connect(h, SIGNAL(downloadFinished(QString, QString)), this, SLOT(handleFavicoDownload(QString, QString)));
connect(h, SIGNAL(downloadFailed(QString, QString)), this, SLOT(handleFavicoFailure(QString, QString))); connect(h, SIGNAL(downloadFailed(QString, QString)), this, SLOT(handleFavicoFailure(QString, QString)));
} }
@ -634,7 +634,7 @@ void TrackerFiltersList::handleFavicoDownload(const QString& url, const QString&
if (url.endsWith(".ico", Qt::CaseInsensitive)) { if (url.endsWith(".ico", Qt::CaseInsensitive)) {
Logger::instance()->addMessage(tr("Couldn't decode favicon for URL `%1`. Trying to download favicon in PNG format.").arg(url), Logger::instance()->addMessage(tr("Couldn't decode favicon for URL `%1`. Trying to download favicon in PNG format.").arg(url),
Log::WARNING); Log::WARNING);
Net::DownloadHandler *h = Net::DownloadManager::instance()->downloadUrl(url.left(url.size() - 4) + ".png"); Net::DownloadHandler *h = Net::DownloadManager::instance()->downloadUrl(url.left(url.size() - 4) + ".png", true);
connect(h, SIGNAL(downloadFinished(QString, QString)), this, SLOT(handleFavicoDownload(QString, QString))); connect(h, SIGNAL(downloadFinished(QString, QString)), this, SLOT(handleFavicoDownload(QString, QString)));
connect(h, SIGNAL(downloadFailed(QString, QString)), this, SLOT(handleFavicoFailure(QString, QString))); connect(h, SIGNAL(downloadFailed(QString, QString)), this, SLOT(handleFavicoFailure(QString, QString)));
} }

View file

@ -413,7 +413,7 @@ bool engineSelectDlg::parseVersionsFile(QString versions_file) {
void engineSelectDlg::downloadFromUrl(const QString &url) void engineSelectDlg::downloadFromUrl(const QString &url)
{ {
Net::DownloadHandler *handler = Net::DownloadManager::instance()->downloadUrl(url); Net::DownloadHandler *handler = Net::DownloadManager::instance()->downloadUrl(url, true);
connect(handler, SIGNAL(downloadFinished(QString, QString)), this, SLOT(processDownloadedFile(QString, QString))); connect(handler, SIGNAL(downloadFinished(QString, QString)), this, SLOT(processDownloadedFile(QString, QString)));
connect(handler, SIGNAL(downloadFailed(QString, QString)), this, SLOT(handleDownloadFailure(QString, QString))); connect(handler, SIGNAL(downloadFailed(QString, QString)), this, SLOT(handleDownloadFailure(QString, QString)));
} }