File indexing completed on 2024-05-12 05:04:25

0001 // SPDX-FileCopyrightText: 2022 Carl Schwan <carl@carlschwan.eu>
0002 // SPDX-License-Identifier: LGPL-2.0-or-later
0003 
0004 #include "filetransferjob.h"
0005 
0006 #include "account.h"
0007 #include "tokodon_http_debug.h"
0008 
0009 #include <KLocalizedString>
0010 
0011 FileTransferJob::FileTransferJob(AbstractAccount *account, const QString &source, const QString &destination)
0012     : KJob()
0013     , m_account(account)
0014     , m_source(source)
0015     , m_destination(destination)
0016     , m_temporaryFile(new QSaveFile(QUrl(destination).toLocalFile()))
0017 {
0018 }
0019 
0020 void FileTransferJob::start()
0021 {
0022     if (auto account = qobject_cast<Account *>(m_account); account) {
0023         auto qnam = account->qnam();
0024 
0025         auto reply = qnam->get(QNetworkRequest(QUrl(m_source)));
0026 
0027         setTotalAmount(Unit::Files, 1);
0028         if (!m_temporaryFile->isReadable() && !m_temporaryFile->open(QIODevice::WriteOnly)) {
0029             qCWarning(TOKODON_HTTP) << "Couldn't open the temporary file" << m_temporaryFile->fileName() << "for writing" << m_temporaryFile->errorString();
0030             setError(FileError);
0031             setErrorText(i18n("Could not open the temporary download file"));
0032             emitResult();
0033             return;
0034         }
0035         connect(reply, &QNetworkReply::downloadProgress, this, [this](qint64 bytesReceived, qint64 bytesTotal) {
0036             if (bytesTotal != -1) {
0037                 setTotalAmount(Unit::Bytes, bytesTotal);
0038             }
0039             setProcessedAmount(Unit::Bytes, bytesReceived);
0040         });
0041 
0042         connect(reply, &QNetworkReply::finished, this, [this, reply]() {
0043             if (reply->error() != QNetworkReply::NoError) {
0044                 setError(FileError);
0045                 setErrorText(reply->errorString());
0046                 emitResult();
0047                 return;
0048             }
0049             if (!m_temporaryFile->commit()) {
0050                 qCWarning(TOKODON_HTTP) << "errror when saving";
0051             }
0052             reply->deleteLater();
0053             emitResult();
0054         });
0055 
0056         connect(reply, &QIODevice::readyRead, this, [this, reply] {
0057             auto bytes = reply->read(reply->bytesAvailable());
0058             if (!bytes.isEmpty()) {
0059                 m_temporaryFile->write(bytes);
0060             } else {
0061                 qCWarning(TOKODON_HTTP) << "Unexpected empty chunk when downloading from" << reply->url() << "to" << m_temporaryFile->fileName();
0062             }
0063         });
0064 
0065         connect(reply, &QNetworkReply::metaDataChanged, this, [this, reply] {
0066             auto sizeHeader = reply->header(QNetworkRequest::ContentLengthHeader);
0067             if (sizeHeader.isValid()) {
0068                 auto targetSize = sizeHeader.toLongLong();
0069                 if (targetSize != -1) {
0070                     if (!m_temporaryFile->resize(targetSize)) {
0071                         qCWarning(TOKODON_HTTP) << "Failed to allocate" << targetSize << "bytes for" << m_temporaryFile->fileName();
0072                         setError(FileError);
0073                         setErrorText(i18n("Could not reserve disk space for download"));
0074                         emitResult();
0075                     }
0076                 }
0077             }
0078         });
0079 
0080         Q_EMIT description(this,
0081                            i18nc("Job heading, like 'Copying'", "Downloading"),
0082                            {i18nc("The URL being downloaded/uploaded", "Source"), m_source},
0083                            {i18nc("The location being downloaded to", "Destination"), m_destination});
0084     }
0085 }