diff options
author | Kitsune Ral <Kitsune-Ral@users.sf.net> | 2018-03-31 20:29:02 +0900 |
---|---|---|
committer | Kitsune Ral <Kitsune-Ral@users.sf.net> | 2018-03-31 20:29:56 +0900 |
commit | a62bc225b8b4c714e7943aad69d84704a03b8015 (patch) | |
tree | df5ff6f4cf878ecd74c14ea41a1d27a46055b415 /lib/jobs/downloadfilejob.cpp | |
parent | 9d8900197e69e9c0ffaaff6f63a40cb80cf08fb1 (diff) | |
parent | 6a61d3a127db1e253821bfb2ebb7f433bd534c4a (diff) | |
download | libquotient-a62bc225b8b4c714e7943aad69d84704a03b8015.tar.gz libquotient-a62bc225b8b4c714e7943aad69d84704a03b8015.zip |
Merge branch 'kitsune-install-target'
Closes #113.
Diffstat (limited to 'lib/jobs/downloadfilejob.cpp')
-rw-r--r-- | lib/jobs/downloadfilejob.cpp | 120 |
1 files changed, 120 insertions, 0 deletions
diff --git a/lib/jobs/downloadfilejob.cpp b/lib/jobs/downloadfilejob.cpp new file mode 100644 index 00000000..6a3d8483 --- /dev/null +++ b/lib/jobs/downloadfilejob.cpp @@ -0,0 +1,120 @@ +#include "downloadfilejob.h" + +#include <QtNetwork/QNetworkReply> +#include <QtCore/QFile> +#include <QtCore/QTemporaryFile> + +using namespace QMatrixClient; + +class DownloadFileJob::Private +{ + public: + Private() : tempFile(new QTemporaryFile()) { } + + explicit Private(const QString& localFilename) + : targetFile(new QFile(localFilename)) + , tempFile(new QFile(targetFile->fileName() + ".qmcdownload")) + { } + + QScopedPointer<QFile> targetFile; + QScopedPointer<QFile> tempFile; +}; + +QUrl DownloadFileJob::makeRequestUrl(QUrl baseUrl, const QUrl& mxcUri) +{ + return makeRequestUrl(baseUrl, mxcUri.authority(), mxcUri.path().mid(1)); +} + +DownloadFileJob::DownloadFileJob(const QString& serverName, + const QString& mediaId, + const QString& localFilename) + : GetContentJob(serverName, mediaId) + , d(localFilename.isEmpty() ? new Private : new Private(localFilename)) +{ + setObjectName("DownloadFileJob"); +} + +QString DownloadFileJob::targetFileName() const +{ + return (d->targetFile ? d->targetFile : d->tempFile)->fileName(); +} + +void DownloadFileJob::beforeStart(const ConnectionData*) +{ + if (d->targetFile && !d->targetFile->isReadable() && + !d->targetFile->open(QIODevice::WriteOnly)) + { + qCWarning(JOBS) << "Couldn't open the file" + << d->targetFile->fileName() << "for writing"; + setStatus(FileError, "Could not open the target file for writing"); + return; + } + if (!d->tempFile->isReadable() && !d->tempFile->open(QIODevice::WriteOnly)) + { + qCWarning(JOBS) << "Couldn't open the temporary file" + << d->tempFile->fileName() << "for writing"; + setStatus(FileError, "Could not open the temporary download file"); + return; + } + qCDebug(JOBS) << "Downloading to" << d->tempFile->fileName(); +} + +void DownloadFileJob::afterStart(const ConnectionData*, QNetworkReply* reply) +{ + connect(reply, &QNetworkReply::metaDataChanged, this, [this,reply] { + auto sizeHeader = reply->header(QNetworkRequest::ContentLengthHeader); + if (sizeHeader.isValid()) + { + auto targetSize = sizeHeader.value<qint64>(); + if (targetSize != -1) + if (!d->tempFile->resize(targetSize)) + { + qCWarning(JOBS) << "Failed to allocate" << targetSize + << "bytes for" << d->tempFile->fileName(); + setStatus(FileError, + "Could not reserve disk space for download"); + } + } + }); + connect(reply, &QIODevice::readyRead, this, [this,reply] { + auto bytes = reply->read(reply->bytesAvailable()); + if (bytes.isEmpty()) + { + qCWarning(JOBS) + << "Unexpected empty chunk when downloading from" + << reply->url() << "to" << d->tempFile->fileName(); + } else { + d->tempFile->write(bytes); + } + }); +} + +void DownloadFileJob::beforeAbandon(QNetworkReply*) +{ + if (d->targetFile) + d->targetFile->remove(); + d->tempFile->remove(); +} + +BaseJob::Status DownloadFileJob::parseReply(QNetworkReply*) +{ + if (d->targetFile) + { + d->targetFile->close(); + if (!d->targetFile->remove()) + { + qCWarning(JOBS) << "Failed to remove the target file placeholder"; + return { FileError, "Couldn't finalise the download" }; + } + if (!d->tempFile->rename(d->targetFile->fileName())) + { + qCWarning(JOBS) << "Failed to rename" << d->tempFile->fileName() + << "to" << d->targetFile->fileName(); + return { FileError, "Couldn't finalise the download" }; + } + } + else + d->tempFile->close(); + qCDebug(JOBS) << "Saved a file as" << targetFileName(); + return Success; +} |