Save partial downloads on disk, not on RAM
This commit is contained in:
parent
62573c21bc
commit
1cbf20f156
@ -39,6 +39,9 @@
|
||||
|
||||
#include "Downloader.h"
|
||||
|
||||
static const QString PARTIAL_DOWN (".part");
|
||||
static const QDir DOWNLOAD_DIR (QDir::homePath() + "/Downloads/");
|
||||
|
||||
Downloader::Downloader (QWidget* parent) : QWidget (parent) {
|
||||
m_ui = new Ui::Downloader;
|
||||
m_ui->setupUi (this);
|
||||
@ -47,7 +50,8 @@ Downloader::Downloader (QWidget* parent) : QWidget (parent) {
|
||||
m_manager = new QNetworkAccessManager();
|
||||
|
||||
/* Initialize internal values */
|
||||
m_filePath = "";
|
||||
m_url = "";
|
||||
m_fileName = "";
|
||||
m_startTime = 0;
|
||||
m_useCustomProcedures = false;
|
||||
|
||||
@ -82,6 +86,17 @@ bool Downloader::useCustomInstallProcedures() const {
|
||||
return m_useCustomProcedures;
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes the URL, which is used to indentify the downloader dialog
|
||||
* with an \c Updater instance
|
||||
*
|
||||
* \note the \a url parameter is not the download URL, it is the URL of
|
||||
* the AppCast file
|
||||
*/
|
||||
void Downloader::setUrlId (const QString& url) {
|
||||
m_url = url;
|
||||
}
|
||||
|
||||
/**
|
||||
* Begins downloading the file at the given \a url
|
||||
*/
|
||||
@ -96,25 +111,42 @@ void Downloader::startDownload (const QUrl& url) {
|
||||
m_startTime = QDateTime::currentDateTime().toTime_t();
|
||||
m_reply = m_manager->get (QNetworkRequest (url));
|
||||
|
||||
/* Ensure that downloads directory exists */
|
||||
if (!DOWNLOAD_DIR.exists())
|
||||
DOWNLOAD_DIR.mkpath (".");
|
||||
|
||||
/* Remove old downloads */
|
||||
QFile::remove (DOWNLOAD_DIR.filePath (m_fileName));
|
||||
QFile::remove (DOWNLOAD_DIR.filePath (m_fileName + PARTIAL_DOWN));
|
||||
|
||||
/* Update UI when download progress changes or download finishes */
|
||||
connect (m_reply, SIGNAL (downloadProgress (qint64, qint64)),
|
||||
this, SLOT (updateProgress (qint64, qint64)));
|
||||
connect (m_reply, SIGNAL (redirected (QUrl)),
|
||||
this, SLOT (startDownload (QUrl)));
|
||||
connect (m_reply, SIGNAL (finished()),
|
||||
this, SLOT (onDownloadFinished()));
|
||||
|
||||
showNormal();
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes the name of the downloaded file
|
||||
*/
|
||||
void Downloader::setFileName (const QString& file) {
|
||||
m_fileName = file;
|
||||
|
||||
if (m_fileName.isEmpty())
|
||||
m_fileName = "QSU_Update.bin";
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens the downloaded file.
|
||||
* \note If the downloaded file is not found, then the function will alert the
|
||||
* user about the error.
|
||||
*/
|
||||
void Downloader::openDownload() {
|
||||
if (!m_filePath.isEmpty())
|
||||
QDesktopServices::openUrl (QUrl::fromLocalFile (m_filePath));
|
||||
if (!m_fileName.isEmpty())
|
||||
QDesktopServices::openUrl (QUrl::fromLocalFile (DOWNLOAD_DIR.filePath (
|
||||
m_fileName)));
|
||||
|
||||
else {
|
||||
QMessageBox::critical (this,
|
||||
@ -136,6 +168,13 @@ void Downloader::installUpdate() {
|
||||
if (useCustomInstallProcedures())
|
||||
return;
|
||||
|
||||
/* Update labels */
|
||||
m_ui->stopButton->setText (tr ("Close"));
|
||||
m_ui->downloadLabel->setText (tr ("Download complete!"));
|
||||
m_ui->timeLabel->setText (tr ("The installer will open separately")
|
||||
+ "...");
|
||||
|
||||
/* Ask the user to install the download */
|
||||
QMessageBox box;
|
||||
box.setIcon (QMessageBox::Question);
|
||||
box.setDefaultButton (QMessageBox::Ok);
|
||||
@ -146,11 +185,13 @@ void Downloader::installUpdate() {
|
||||
"quit the application.")
|
||||
+ "</h3>");
|
||||
|
||||
/* User wants to install the download */
|
||||
if (box.exec() == QMessageBox::Ok) {
|
||||
if (!useCustomInstallProcedures())
|
||||
openDownload();
|
||||
}
|
||||
|
||||
/* Wait */
|
||||
else {
|
||||
m_ui->openButton->setEnabled (true);
|
||||
m_ui->openButton->setVisible (true);
|
||||
@ -182,24 +223,9 @@ void Downloader::cancelDownload() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes the downloaded data to a temp. directory and updates the UI controls.
|
||||
* \note If the function detects that the downloaded data is an HTML file
|
||||
* (e.g. a redirection notice from the server), the function will add the
|
||||
* *.html extension to the downloaded file. This ensures that the download
|
||||
* will be resumed when the OS opens a web-browser with the redirection
|
||||
* notice.
|
||||
* Writes the downloaded data to the disk
|
||||
*/
|
||||
void Downloader::onDownloadFinished() {
|
||||
m_ui->stopButton->setText (tr ("Close"));
|
||||
m_ui->downloadLabel->setText (tr ("Download complete!"));
|
||||
m_ui->timeLabel->setText (tr ("The installer will open separately")
|
||||
+ "...");
|
||||
|
||||
QByteArray data = m_reply->readAll();
|
||||
|
||||
if (!data.isEmpty()) {
|
||||
QString name = m_reply->url().toString().split ("/").last();
|
||||
|
||||
void Downloader::saveFile (qint64 received, qint64 total) {
|
||||
/* Check if we need to redirect */
|
||||
QUrl url = m_reply->attribute (
|
||||
QNetworkRequest::RedirectionTargetAttribute).toUrl();
|
||||
@ -209,21 +235,28 @@ void Downloader::onDownloadFinished() {
|
||||
}
|
||||
|
||||
/* Save downloaded data to disk */
|
||||
QFile file (QDir::tempPath() + "/" + name);
|
||||
if (file.open (QIODevice::WriteOnly)) {
|
||||
file.write (data);
|
||||
QFile file (DOWNLOAD_DIR.filePath (m_fileName + PARTIAL_DOWN));
|
||||
if (file.open (QIODevice::WriteOnly | QIODevice::Append)) {
|
||||
file.write (m_reply->readAll());
|
||||
file.close();
|
||||
|
||||
m_filePath = file.fileName();
|
||||
emit downloadFinished (m_reply->url().toString(), m_filePath);
|
||||
}
|
||||
|
||||
/* Open downloaded update */
|
||||
if (received >= total && total > 0) {
|
||||
/* Rename file */
|
||||
QFile::rename (DOWNLOAD_DIR.filePath (m_fileName + PARTIAL_DOWN),
|
||||
DOWNLOAD_DIR.filePath (m_fileName));
|
||||
|
||||
/* Notify application */
|
||||
emit downloadFinished (m_url, DOWNLOAD_DIR.filePath (m_fileName));
|
||||
|
||||
/* Install the update */
|
||||
m_reply->close();
|
||||
installUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Calculates the appropiate size units (bytes, KB or MB) for the received
|
||||
* data and the total download size. Then, this function proceeds to update the
|
||||
@ -268,6 +301,7 @@ void Downloader::updateProgress (qint64 received, qint64 total) {
|
||||
|
||||
calculateSizes (received, total);
|
||||
calculateTimeRemaining (received, total);
|
||||
saveFile (received, total);
|
||||
}
|
||||
|
||||
else {
|
||||
|
@ -56,14 +56,16 @@ class Downloader : public QWidget {
|
||||
bool useCustomInstallProcedures() const;
|
||||
|
||||
public slots:
|
||||
void setUrlId (const QString& url);
|
||||
void startDownload (const QUrl& url);
|
||||
void setFileName (const QString& file);
|
||||
void setUseCustomInstallProcedures (const bool custom);
|
||||
|
||||
private slots:
|
||||
void openDownload();
|
||||
void installUpdate();
|
||||
void cancelDownload();
|
||||
void onDownloadFinished();
|
||||
void saveFile (qint64 received, qint64 total);
|
||||
void calculateSizes (qint64 received, qint64 total);
|
||||
void updateProgress (qint64 received, qint64 total);
|
||||
void calculateTimeRemaining (qint64 received, qint64 total);
|
||||
@ -72,8 +74,9 @@ class Downloader : public QWidget {
|
||||
qreal round (const qreal& input);
|
||||
|
||||
private:
|
||||
QString m_url;
|
||||
uint m_startTime;
|
||||
QString m_filePath;
|
||||
QString m_fileName;
|
||||
Ui::Downloader* m_ui;
|
||||
QNetworkReply* m_reply;
|
||||
bool m_useCustomProcedures;
|
||||
|
@ -362,8 +362,11 @@ void Updater::setUpdateAvailable (const bool available) {
|
||||
if (!openUrl().isEmpty())
|
||||
QDesktopServices::openUrl (QUrl (openUrl()));
|
||||
|
||||
else if (downloaderEnabled())
|
||||
else if (downloaderEnabled()) {
|
||||
m_downloader->setUrlId (url());
|
||||
m_downloader->setFileName (downloadUrl().split ("/").last());
|
||||
m_downloader->startDownload (QUrl (downloadUrl()));
|
||||
}
|
||||
|
||||
else
|
||||
QDesktopServices::openUrl (QUrl (downloadUrl()));
|
||||
|
Loading…
x
Reference in New Issue
Block a user