Warning, file /network/ruqola/src/rocketchatrestapi-qt/uploadfilejob.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001 /* 0002 SPDX-FileCopyrightText: 2018-2024 Laurent Montel <montel@kde.org> 0003 0004 SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #include "uploadfilejob.h" 0008 #include "restapimethod.h" 0009 #include "rocketchatqtrestapi_debug.h" 0010 #include <KLocalizedString> 0011 #include <QFile> 0012 #include <QHttpMultiPart> 0013 #include <QJsonDocument> 0014 #include <QJsonObject> 0015 #include <QMimeDatabase> 0016 #include <QNetworkReply> 0017 0018 using namespace RocketChatRestApi; 0019 0020 UploadFileJob::UploadFileJob(QObject *parent) 0021 : RestApiAbstractJob(parent) 0022 { 0023 } 0024 0025 UploadFileJob::~UploadFileJob() = default; 0026 0027 bool UploadFileJob::canStart() const 0028 { 0029 if (!RestApiAbstractJob::canStart()) { 0030 return false; 0031 } 0032 if (mUploadFileInfo.roomId.isEmpty()) { 0033 qCWarning(ROCKETCHATQTRESTAPI_LOG) << "UploadFileJob : RoomId not defined"; 0034 return false; 0035 } 0036 if (!mUploadFileInfo.filenameUrl.isLocalFile()) { 0037 // shouldn't be too hard, just use KIO::storedGet 0038 qCWarning(ROCKETCHATQTRESTAPI_LOG) << "Uploading remote files is not supported yet"; 0039 return false; 0040 } 0041 return true; 0042 } 0043 0044 bool UploadFileJob::start() 0045 { 0046 if (!canStart()) { 0047 deleteLater(); 0048 return false; 0049 } 0050 const QString fileNameAsLocalFile = mUploadFileInfo.filenameUrl.toLocalFile(); 0051 auto file = new QFile(fileNameAsLocalFile); 0052 if (!file->open(QIODevice::ReadOnly)) { 0053 qCWarning(ROCKETCHATQTRESTAPI_LOG) << " Impossible to open filename " << mUploadFileInfo.filenameUrl; 0054 Q_EMIT failed(i18n("File not found \'%1\'", fileNameAsLocalFile)); 0055 delete file; 0056 deleteLater(); 0057 return false; 0058 } 0059 QMimeDatabase db; 0060 const QMimeType mimeType = db.mimeTypeForFile(fileNameAsLocalFile); 0061 0062 auto multiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType); 0063 0064 QHttpPart filePart; 0065 filePart.setHeader(QNetworkRequest::ContentTypeHeader, QVariant(mimeType.name())); 0066 const QString filePartInfo = QStringLiteral("form-data; name=\"file\"; filename=\"%1\"") 0067 .arg(mUploadFileInfo.fileName.isEmpty() ? mUploadFileInfo.filenameUrl.fileName() : mUploadFileInfo.fileName); 0068 filePart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant(filePartInfo)); 0069 0070 filePart.setBodyDevice(file); 0071 file->setParent(multiPart); // we cannot delete the file now, so delete it with the multiPart 0072 multiPart->append(filePart); 0073 0074 QHttpPart msgPart; 0075 msgPart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant(QLatin1String("form-data; name=\"msg\""))); 0076 msgPart.setBody(mUploadFileInfo.messageText.toUtf8()); 0077 multiPart->append(msgPart); 0078 0079 if (!mUploadFileInfo.threadMessageId.isEmpty()) { 0080 QHttpPart msgPart; 0081 msgPart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant(QLatin1String("form-data; name=\"tmid\""))); 0082 msgPart.setBody(mUploadFileInfo.threadMessageId.toUtf8()); 0083 multiPart->append(msgPart); 0084 } 0085 0086 QHttpPart descriptionPart; 0087 descriptionPart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant(QLatin1String("form-data; name=\"description\""))); 0088 descriptionPart.setBody(mUploadFileInfo.description.toUtf8()); 0089 multiPart->append(descriptionPart); 0090 mReply = networkAccessManager()->post(request(), multiPart); 0091 connect(mReply, &QNetworkReply::uploadProgress, this, &UploadFileJob::slotUploadProgress); 0092 connect(mReply, &QNetworkReply::finished, this, &UploadFileJob::slotUploadFinished); 0093 multiPart->setParent(mReply); // delete the multiPart with the reply 0094 // TODO signal error ? 0095 addStartRestApiInfo("UploadFileJob::start"); 0096 return true; 0097 } 0098 0099 void UploadFileJob::slotUploadProgress(qint64 bytesSent, qint64 bytesTotal) 0100 { 0101 UploadFileJob::UploadStatusInfo info; 0102 info.bytesSent = bytesSent; 0103 info.bytesTotal = bytesTotal; 0104 info.fileName = mUploadFileInfo.filenameUrl.fileName(); 0105 Q_EMIT uploadProgress(info); 0106 } 0107 0108 QNetworkRequest UploadFileJob::request() const 0109 { 0110 const QUrl url = mRestApiMethod->generateUrl(RestApiUtil::RestApiUrlType::RoomsUpload, mUploadFileInfo.roomId); 0111 QNetworkRequest request(url); 0112 addAuthRawHeader(request); 0113 addRequestAttribute(request, false); 0114 0115 return request; 0116 } 0117 0118 void UploadFileJob::abort() 0119 { 0120 if (mReply) { 0121 mReply->abort(); 0122 } 0123 deleteLater(); 0124 } 0125 0126 void UploadFileJob::slotUploadFinished() 0127 { 0128 auto reply = mReply; 0129 if (reply) { 0130 const QJsonDocument replyJson = convertToJsonDocument(reply); 0131 const QJsonObject replyObject = replyJson.object(); 0132 if (replyObject.value(QLatin1String("success")).toBool()) { 0133 addLoggerInfo(QByteArrayLiteral("UploadFileJob: success: ") + replyJson.toJson(QJsonDocument::Indented)); 0134 } else { 0135 if (reply->error() != QNetworkReply::NoError) { 0136 if (mReply->error() == QNetworkReply::NetworkSessionFailedError) { 0137 qCWarning(ROCKETCHATQTRESTAPI_LOG) << metaObject()->className() << "NetworkSessionFailedError. Connection loss?"; 0138 deleteLater(); 0139 return; 0140 } 0141 // TODO verify it ! 0142 Q_EMIT failed(mReply->errorString() + QLatin1Char('\n') + errorStr(replyObject)); 0143 } else { 0144 emitFailedMessage(reply->errorString(), replyObject); 0145 addLoggerWarning(QByteArrayLiteral("UploadFileJob: Problem: ") + replyJson.toJson(QJsonDocument::Indented)); 0146 } 0147 } 0148 reply->deleteLater(); 0149 } 0150 Q_EMIT uploadFinished(); 0151 deleteLater(); 0152 } 0153 0154 UploadFileJob::UploadFileInfo UploadFileJob::uploadFileInfo() const 0155 { 0156 return mUploadFileInfo; 0157 } 0158 0159 void UploadFileJob::setUploadFileInfo(const UploadFileInfo &uploadFileInfo) 0160 { 0161 mUploadFileInfo = uploadFileInfo; 0162 } 0163 0164 bool UploadFileJob::requireHttpAuthentication() const 0165 { 0166 return true; 0167 } 0168 0169 bool UploadFileJob::UploadFileInfo::isValid() const 0170 { 0171 return !roomId.isEmpty() && !filenameUrl.isEmpty(); 0172 } 0173 0174 #include "moc_uploadfilejob.cpp"