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