able to send file

This commit is contained in:
2026-04-27 16:08:40 +08:00
parent 71ea3dbd01
commit bfe271550e
6 changed files with 419 additions and 15 deletions

View File

@@ -6,6 +6,7 @@
#include <QStandardPaths> #include <QStandardPaths>
#include <QUrl> #include <QUrl>
#include <QDebug> #include <QDebug>
#include <QMimeDatabase>
AppController::AppController(QObject* parent) AppController::AppController(QObject* parent)
: QObject(parent) : QObject(parent)
@@ -14,6 +15,7 @@ AppController::AppController(QObject* parent)
, m_discovery(new LocalSend::DiscoveryManager(this)) , m_discovery(new LocalSend::DiscoveryManager(this))
, m_server(new LocalSend::HttpServer(this)) , m_server(new LocalSend::HttpServer(this))
, m_sessions(new LocalSend::SessionManager(this)) , m_sessions(new LocalSend::SessionManager(this))
, m_httpClient(new LocalSend::HttpClient(this))
{ {
} }
@@ -54,6 +56,17 @@ void AppController::initialize()
connect(m_sessions, &LocalSend::SessionManager::receiveSessionCompleted, connect(m_sessions, &LocalSend::SessionManager::receiveSessionCompleted,
this, &AppController::onReceiveCompleted); this, &AppController::onReceiveCompleted);
connect(m_httpClient, &LocalSend::HttpClient::prepareUploadResponse,
this, &AppController::onPrepareUploadResponse);
connect(m_httpClient, &LocalSend::HttpClient::prepareUploadError,
this, &AppController::onPrepareUploadError);
connect(m_httpClient, &LocalSend::HttpClient::uploadProgress,
this, &AppController::onUploadProgress);
connect(m_httpClient, &LocalSend::HttpClient::uploadCompleted,
this, &AppController::onUploadCompleted);
connect(m_httpClient, &LocalSend::HttpClient::uploadError,
this, &AppController::onUploadError);
startDiscovery(); startDiscovery();
} }
@@ -345,3 +358,227 @@ void AppController::onReceiveCompleted(const QString& sessionId)
{ {
emit receiveCompleted(sessionId); emit receiveCompleted(sessionId);
} }
bool AppController::sending() const
{
return !m_currentSendSessionId.isEmpty();
}
double AppController::sendProgress() const
{
return m_sendProgress;
}
void AppController::sendFiles(const QString& deviceFingerprint, const QStringList& filePaths)
{
if (!m_devices.contains(deviceFingerprint)) {
emit sendError(QStringLiteral("Device not found"));
return;
}
if (filePaths.isEmpty()) {
emit sendError(QStringLiteral("No files selected"));
return;
}
if (sending()) {
emit sendError(QStringLiteral("Already sending files"));
return;
}
m_currentSendDeviceFingerprint = deviceFingerprint;
m_pendingFiles = filePaths;
m_currentFileIndex = 0;
m_sendProgress = 0.0;
emit sendingChanged();
emit sendProgressChanged();
qDebug() << "[AppController] sendFiles: device=" << deviceFingerprint
<< "files=" << filePaths.size();
LocalSend::Device target = m_devices[deviceFingerprint];
QMap<QString, LocalSend::FileDto> files;
QMimeDatabase mimeDb;
for (int i = 0; i < filePaths.size(); ++i) {
QString filePath = filePaths[i];
QFileInfo info(filePath);
if (!info.exists()) {
emit sendError(QStringLiteral("File not found: ") + filePath);
m_currentSendSessionId.clear();
emit sendingChanged();
return;
}
LocalSend::FileDto fileDto;
fileDto.id = QString::number(i);
fileDto.fileName = info.fileName();
fileDto.size = info.size();
fileDto.fileType = mimeDb.mimeTypeForFile(filePath).name();
files.insert(fileDto.id, fileDto);
}
m_currentSendSessionId = m_sessions->createSendSession(target, files,
[filePaths]() {
QMap<QString, QString> paths;
for (int i = 0; i < filePaths.size(); ++i) {
paths.insert(QString::number(i), filePaths[i]);
}
return paths;
}()
);
LocalSend::PrepareUploadRequestDto request;
request.info = buildRegisterDto();
request.files = files;
qDebug() << "[AppController] Sending prepare-upload request to" << target.ip;
m_httpClient->prepareUpload(target, request);
}
void AppController::cancelSend()
{
if (m_currentSendSessionId.isEmpty()) {
return;
}
LocalSend::Device target = m_devices.value(m_currentSendDeviceFingerprint);
m_httpClient->cancel(target, m_currentSendSessionId);
m_sessions->cancelSendSession(m_currentSendSessionId);
m_currentSendSessionId.clear();
m_pendingFiles.clear();
m_sendProgress = 0.0;
emit sendingChanged();
emit sendProgressChanged();
}
void AppController::onPrepareUploadResponse(const LocalSend::PrepareUploadResponseDto& response)
{
qDebug() << "[AppController] onPrepareUploadResponse: sessionId=" << response.sessionId
<< "files=" << response.files.size();
LocalSend::SendSession session = m_sessions->sendSession(m_currentSendSessionId);
if (session.sessionId.isEmpty()) {
emit sendError(QStringLiteral("Session not found"));
m_currentSendSessionId.clear();
emit sendingChanged();
return;
}
if (response.files.isEmpty()) {
emit sendError(QStringLiteral("Receiver declined the transfer"));
m_currentSendSessionId.clear();
emit sendingChanged();
return;
}
m_sessions->setSendSessionTokens(m_currentSendSessionId, response.sessionId, response.files);
m_currentSendSessionId = response.sessionId;
m_sessions->startSendSession(m_currentSendSessionId);
m_currentFileIndex = 0;
sendNextFile();
}
void AppController::onPrepareUploadError(const QString& error)
{
qWarning() << "[AppController] onPrepareUploadError:" << error;
emit sendError(error);
m_currentSendSessionId.clear();
emit sendingChanged();
}
void AppController::onUploadProgress(qint64 sent, qint64 total)
{
if (total > 0) {
double fileProgress = static_cast<double>(sent) / total;
int totalFiles = m_pendingFiles.size();
double overallProgress = (m_currentFileIndex + fileProgress) / totalFiles;
m_sendProgress = overallProgress * 100.0;
emit sendProgressChanged();
}
}
void AppController::onUploadCompleted()
{
qDebug() << "[AppController] onUploadCompleted, file index:" << m_currentFileIndex;
m_sessions->completeSendFile(m_currentSendSessionId, m_currentSendFileId);
m_currentFileIndex++;
if (m_currentFileIndex < m_pendingFiles.size()) {
sendNextFile();
} else {
qDebug() << "[AppController] All files sent successfully";
m_sendProgress = 100.0;
emit sendProgressChanged();
emit sendCompleted(m_currentSendSessionId);
m_currentSendSessionId.clear();
emit sendingChanged();
}
}
void AppController::onUploadError(const QString& error)
{
qWarning() << "[AppController] onUploadError:" << error;
emit sendError(error);
m_sessions->failSendFile(m_currentSendSessionId, m_currentSendFileId);
m_currentSendSessionId.clear();
emit sendingChanged();
}
void AppController::sendNextFile()
{
if (m_currentFileIndex >= m_pendingFiles.size()) {
return;
}
LocalSend::SendSession session = m_sessions->sendSession(m_currentSendSessionId);
if (session.sessionId.isEmpty()) {
qWarning() << "[AppController] Session not found:" << m_currentSendSessionId;
return;
}
QString fileId = QString::number(m_currentFileIndex);
if (!session.files.contains(fileId)) {
qWarning() << "[AppController] File not found in session:" << fileId;
return;
}
m_currentSendFileId = fileId;
QString filePath = m_pendingFiles[m_currentFileIndex];
QString token = session.files[fileId].token;
LocalSend::Device target = m_devices.value(m_currentSendDeviceFingerprint);
qDebug() << "[AppController] Uploading file" << fileId << ":" << filePath
<< "token:" << token << "to" << target.ip;
if (token.isEmpty()) {
emit sendError(QStringLiteral("No token for file: ") + fileId);
m_currentSendSessionId.clear();
emit sendingChanged();
return;
}
m_httpClient->uploadFile(target, m_currentSendSessionId, fileId, token, filePath);
}
LocalSend::RegisterDto AppController::buildRegisterDto() const
{
LocalSend::RegisterDto dto;
dto.alias = m_settings->alias();
dto.version = m_settings->version();
dto.deviceModel = m_settings->deviceModel();
dto.deviceType = m_settings->deviceType();
dto.fingerprint = m_security->fingerprint();
dto.port = m_settings->port();
dto.protocol = m_settings->https() ? LocalSend::ProtocolType::Https : LocalSend::ProtocolType::Http;
dto.download = false;
return dto;
}

View File

@@ -19,6 +19,8 @@ class AppController : public QObject
Q_PROPERTY(bool serverRunning READ serverRunning NOTIFY serverRunningChanged) Q_PROPERTY(bool serverRunning READ serverRunning NOTIFY serverRunningChanged)
Q_PROPERTY(QString downloadPath READ downloadPath WRITE setDownloadPath NOTIFY downloadPathChanged) Q_PROPERTY(QString downloadPath READ downloadPath WRITE setDownloadPath NOTIFY downloadPathChanged)
Q_PROPERTY(bool quickSave READ quickSave WRITE setQuickSave NOTIFY quickSaveChanged) Q_PROPERTY(bool quickSave READ quickSave WRITE setQuickSave NOTIFY quickSaveChanged)
Q_PROPERTY(bool sending READ sending NOTIFY sendingChanged)
Q_PROPERTY(double sendProgress READ sendProgress NOTIFY sendProgressChanged)
public: public:
explicit AppController(QObject* parent = nullptr); explicit AppController(QObject* parent = nullptr);
@@ -41,6 +43,9 @@ public:
QVariantList devices() const; QVariantList devices() const;
bool serverRunning() const; bool serverRunning() const;
bool sending() const;
double sendProgress() const;
Q_INVOKABLE void startDiscovery(); Q_INVOKABLE void startDiscovery();
Q_INVOKABLE void stopDiscovery(); Q_INVOKABLE void stopDiscovery();
Q_INVOKABLE void refreshDevices(); Q_INVOKABLE void refreshDevices();
@@ -48,6 +53,9 @@ public:
Q_INVOKABLE void acceptReceive(const QString& sessionId); Q_INVOKABLE void acceptReceive(const QString& sessionId);
Q_INVOKABLE void declineReceive(const QString& sessionId); Q_INVOKABLE void declineReceive(const QString& sessionId);
Q_INVOKABLE void sendFiles(const QString& deviceFingerprint, const QStringList& filePaths);
Q_INVOKABLE void cancelSend();
signals: signals:
void aliasChanged(); void aliasChanged();
void portChanged(); void portChanged();
@@ -55,13 +63,15 @@ signals:
void quickSaveChanged(); void quickSaveChanged();
void devicesChanged(); void devicesChanged();
void serverRunningChanged(); void serverRunningChanged();
void sendingChanged();
void sendProgressChanged();
void receiveRequest(const QString& sessionId, const QString& senderAlias, void receiveRequest(const QString& sessionId, const QString& senderAlias,
const QString& senderIp, const QVariantList& files); const QString& senderIp, const QVariantList& files);
void receiveProgress(const QString& sessionId, const QString& fileId, double progress); void receiveProgress(const QString& sessionId, const QString& fileId, double progress);
void receiveCompleted(const QString& sessionId); void receiveCompleted(const QString& sessionId);
void receiveError(const QString& sessionId, const QString& error); void receiveError(const QString& sessionId, const QString& error);
void sendProgress(const QString& sessionId, double progress);
void sendCompleted(const QString& sessionId); void sendCompleted(const QString& sessionId);
void sendError(const QString& error);
private slots: private slots:
void onDeviceDiscovered(const LocalSend::Device& device); void onDeviceDiscovered(const LocalSend::Device& device);
@@ -77,15 +87,31 @@ private slots:
void onReceiveProgress(const QString& sessionId, const QString& fileId, double progress); void onReceiveProgress(const QString& sessionId, const QString& fileId, double progress);
void onReceiveCompleted(const QString& sessionId); void onReceiveCompleted(const QString& sessionId);
void onPrepareUploadResponse(const LocalSend::PrepareUploadResponseDto& response);
void onPrepareUploadError(const QString& error);
void onUploadProgress(qint64 sent, qint64 total);
void onUploadCompleted();
void onUploadError(const QString& error);
private: private:
LocalSend::Settings* m_settings = nullptr; LocalSend::Settings* m_settings = nullptr;
LocalSend::SecurityContext* m_security = nullptr; LocalSend::SecurityContext* m_security = nullptr;
LocalSend::DiscoveryManager* m_discovery = nullptr; LocalSend::DiscoveryManager* m_discovery = nullptr;
LocalSend::HttpServer* m_server = nullptr; LocalSend::HttpServer* m_server = nullptr;
LocalSend::SessionManager* m_sessions = nullptr; LocalSend::SessionManager* m_sessions = nullptr;
LocalSend::HttpClient* m_httpClient = nullptr;
QMap<QString, LocalSend::Device> m_devices; QMap<QString, LocalSend::Device> m_devices;
QString m_currentSendSessionId;
QString m_currentSendFileId;
QString m_currentSendDeviceFingerprint;
QStringList m_pendingFiles;
int m_currentFileIndex = 0;
double m_sendProgress = 0.0;
LocalSend::InfoDto buildInfoDto() const; LocalSend::InfoDto buildInfoDto() const;
QString generateUniqueFilePath(const QString& baseDir, const QString& fileName) const; QString generateUniqueFilePath(const QString& baseDir, const QString& fileName) const;
void sendNextFile();
LocalSend::RegisterDto buildRegisterDto() const;
}; };

View File

@@ -15,6 +15,7 @@ ApplicationWindow {
property string currentSenderAlias: "" property string currentSenderAlias: ""
property string currentSenderIp: "" property string currentSenderIp: ""
property var receiveProgress: ({}) property var receiveProgress: ({})
property string selectedDeviceFingerprint: ""
StackView { StackView {
id: stackView id: stackView
@@ -25,6 +26,21 @@ ApplicationWindow {
} }
} }
FileDialog {
id: fileDialog
title: qsTr("Select Files to Send")
fileMode: FileDialog.OpenFiles
onAccepted: {
var paths = []
for (var i = 0; i < selectedFiles.length; i++) {
paths.push(selectedFiles[i].toString().replace("file://", ""))
}
if (paths.length > 0 && selectedDeviceFingerprint !== "") {
appController.sendFiles(selectedDeviceFingerprint, paths)
}
}
}
Dialog { Dialog {
id: receiveDialog id: receiveDialog
anchors.centerIn: parent anchors.centerIn: parent
@@ -73,7 +89,7 @@ ApplicationWindow {
} }
Label { Label {
text: formatSize(modelData.size) text: formatSize(modelData.size)
color: "gray" color: palette.mid
} }
} }
} }
@@ -87,7 +103,7 @@ ApplicationWindow {
} }
Dialog { Dialog {
id: progressDialog id: receiveProgressDialog
anchors.centerIn: parent anchors.centerIn: parent
modal: true modal: true
closePolicy: Popup.NoAutoClose closePolicy: Popup.NoAutoClose
@@ -97,12 +113,10 @@ ApplicationWindow {
spacing: 12 spacing: 12
Label { Label {
id: progressLabel
text: qsTr("Receiving from %1...").arg(currentSenderAlias) text: qsTr("Receiving from %1...").arg(currentSenderAlias)
} }
ProgressBar { ProgressBar {
id: totalProgressBar
Layout.fillWidth: true Layout.fillWidth: true
from: 0 from: 0
to: 100 to: 100
@@ -110,14 +124,53 @@ ApplicationWindow {
} }
Label { Label {
text: qsTr("%1% complete").arg(Math.round(totalProgressBar.value)) text: qsTr("%1% complete").arg(Math.round(calculateTotalProgress()))
color: "gray" color: palette.mid
} }
} }
property var progressData: ({}) property var progressData: ({})
} }
Dialog {
id: sendProgressDialog
anchors.centerIn: parent
modal: true
closePolicy: Popup.NoAutoClose
title: qsTr("Sending Files")
ColumnLayout {
spacing: 12
Label {
text: qsTr("Sending files...")
}
ProgressBar {
Layout.fillWidth: true
from: 0
to: 100
value: appController.sendProgress
}
Label {
text: qsTr("%1% complete").arg(Math.round(appController.sendProgress))
color: palette.mid
}
}
footer: DialogButtonBox {
Button {
text: qsTr("Cancel")
DialogButtonBox.buttonRole: DialogButtonBox.RejectRole
onClicked: {
appController.cancelSend()
sendProgressDialog.close()
}
}
}
}
Connections { Connections {
target: appController target: appController
@@ -129,6 +182,7 @@ ApplicationWindow {
if (appController.quickSave) { if (appController.quickSave) {
appController.acceptReceive(sessionId) appController.acceptReceive(sessionId)
receiveProgressDialog.open()
} else { } else {
receiveDialog.open() receiveDialog.open()
} }
@@ -138,13 +192,17 @@ ApplicationWindow {
if (sessionId === currentSessionId) { if (sessionId === currentSessionId) {
receiveProgress[fileId] = progress receiveProgress[fileId] = progress
receiveProgress = Object.assign({}, receiveProgress) receiveProgress = Object.assign({}, receiveProgress)
progressDialog.progressData = receiveProgress receiveProgressDialog.progressData = receiveProgress
if (!receiveProgressDialog.visible) {
receiveProgressDialog.open()
}
} }
} }
function onReceiveCompleted(sessionId) { function onReceiveCompleted(sessionId) {
if (sessionId === currentSessionId) { if (sessionId === currentSessionId) {
progressDialog.close() receiveProgressDialog.close()
receiveProgress = {} receiveProgress = {}
currentSessionId = "" currentSessionId = ""
} }
@@ -152,11 +210,29 @@ ApplicationWindow {
function onReceiveError(sessionId, error) { function onReceiveError(sessionId, error) {
if (sessionId === currentSessionId) { if (sessionId === currentSessionId) {
progressDialog.close() receiveProgressDialog.close()
errorDialog.text = error errorDialog.text = error
errorDialog.open() errorDialog.open()
} }
} }
function onSendProgress(progress) {
if (!sendProgressDialog.visible) {
sendProgressDialog.open()
}
}
function onSendCompleted(sessionId) {
sendProgressDialog.close()
successDialog.text = qsTr("Files sent successfully!")
successDialog.open()
}
function onSendError(error) {
sendProgressDialog.close()
errorDialog.text = error
errorDialog.open()
}
} }
Dialog { Dialog {
@@ -172,6 +248,19 @@ ApplicationWindow {
} }
} }
Dialog {
id: successDialog
anchors.centerIn: parent
modal: true
standardButtons: Dialog.Ok
title: qsTr("Success")
property alias text: successLabel.text
Label {
id: successLabel
}
}
function formatSize(bytes) { function formatSize(bytes) {
if (bytes < 1024) return bytes + " B" if (bytes < 1024) return bytes + " B"
if (bytes < 1024 * 1024) return (bytes / 1024).toFixed(1) + " KB" if (bytes < 1024 * 1024) return (bytes / 1024).toFixed(1) + " KB"
@@ -242,8 +331,10 @@ ApplicationWindow {
padding: 12 padding: 12
background: Rectangle { background: Rectangle {
color: Qt.lighter("gray", 1.8) color: "transparent"
radius: 8 radius: 8
border.color: palette.mid
border.width: 1
} }
RowLayout { RowLayout {
@@ -257,19 +348,28 @@ ApplicationWindow {
} }
Label { Label {
text: "%1:%2".arg(modelData.ip).arg(modelData.port) text: "%1:%2".arg(modelData.ip).arg(modelData.port)
color: "gray" color: palette.mid
font.pixelSize: 12 font.pixelSize: 12
} }
} }
Button { Button {
text: qsTr("Send") text: qsTr("Send")
enabled: !appController.sending
onClicked: { onClicked: {
// TODO: send to this device selectedDeviceFingerprint = modelData.fingerprint
fileDialog.open()
} }
} }
} }
} }
Label {
anchors.centerIn: parent
text: qsTr("No devices found")
color: palette.mid
visible: deviceListView.count === 0
}
} }
RowLayout { RowLayout {

View File

@@ -53,6 +53,8 @@ public:
QString createSendSession(const Device& target, const QMap<QString, FileDto>& files, QString createSendSession(const Device& target, const QMap<QString, FileDto>& files,
const QMap<QString, QString>& localPaths); const QMap<QString, QString>& localPaths);
void setSendSessionTokens(const QString& sessionId, const QString& responseSessionId,
const QMap<QString, QString>& tokens);
void startSendSession(const QString& sessionId); void startSendSession(const QString& sessionId);
void updateSendProgress(const QString& sessionId, const QString& fileId, qint64 bytes); void updateSendProgress(const QString& sessionId, const QString& fileId, qint64 bytes);
void completeSendFile(const QString& sessionId, const QString& fileId); void completeSendFile(const QString& sessionId, const QString& fileId);

View File

@@ -3,6 +3,7 @@
#include <QFile> #include <QFile>
#include <QUrlQuery> #include <QUrlQuery>
#include <QJsonDocument> #include <QJsonDocument>
#include <QDebug>
namespace LocalSend { namespace LocalSend {
@@ -10,6 +11,10 @@ HttpClient::HttpClient(QObject* parent)
: QObject(parent) : QObject(parent)
, m_manager(new QNetworkAccessManager(this)) , m_manager(new QNetworkAccessManager(this))
{ {
connect(m_manager, &QNetworkAccessManager::sslErrors,
this, [](QNetworkReply* reply, const QList<QSslError>&) {
reply->ignoreSslErrors();
});
} }
HttpClient::~HttpClient() HttpClient::~HttpClient()
@@ -98,20 +103,29 @@ void HttpClient::prepareUpload(const Device& device, const PrepareUploadRequestD
{ {
QUrl url = buildUrl(device, ApiRoute::PREPARE_UPLOAD); QUrl url = buildUrl(device, ApiRoute::PREPARE_UPLOAD);
QByteArray data = QJsonDocument(dto.toJson()).toJson(QJsonDocument::Compact); QByteArray data = QJsonDocument(dto.toJson()).toJson(QJsonDocument::Compact);
qDebug() << "[HttpClient] prepareUpload to" << url.toString();
qDebug() << "[HttpClient] request:" << data;
QNetworkReply* reply = sendPost(url, data); QNetworkReply* reply = sendPost(url, data);
connect(reply, &QNetworkReply::finished, this, [this, reply]() { connect(reply, &QNetworkReply::finished, this, [this, reply]() {
reply->deleteLater(); reply->deleteLater();
if (reply->error() != QNetworkReply::NoError) { if (reply->error() != QNetworkReply::NoError) {
qWarning() << "[HttpClient] prepareUpload error:" << reply->errorString();
emit prepareUploadError(reply->errorString()); emit prepareUploadError(reply->errorString());
return; return;
} }
QByteArray responseData = reply->readAll();
qDebug() << "[HttpClient] prepareUpload response:" << responseData;
QJsonParseError error; QJsonParseError error;
QJsonDocument doc = QJsonDocument::fromJson(reply->readAll(), &error); QJsonDocument doc = QJsonDocument::fromJson(responseData, &error);
if (error.error != QJsonParseError::NoError) { if (error.error != QJsonParseError::NoError) {
qWarning() << "[HttpClient] Invalid JSON response";
emit prepareUploadError(QStringLiteral("Invalid JSON response")); emit prepareUploadError(QStringLiteral("Invalid JSON response"));
return; return;
} }
@@ -131,14 +145,18 @@ void HttpClient::uploadFile(const Device& device, const QString& sessionId,
query.addQueryItem(QStringLiteral("token"), token); query.addQueryItem(QStringLiteral("token"), token);
url.setQuery(query); url.setQuery(query);
qDebug() << "[HttpClient] uploadFile to" << url.toString();
QFile* file = new QFile(filePath); QFile* file = new QFile(filePath);
if (!file->open(QIODevice::ReadOnly)) { if (!file->open(QIODevice::ReadOnly)) {
qWarning() << "[HttpClient] Cannot open file:" << filePath << file->errorString();
emit uploadError(QStringLiteral("Cannot open file: ") + file->errorString()); emit uploadError(QStringLiteral("Cannot open file: ") + file->errorString());
delete file; delete file;
return; return;
} }
qint64 fileSize = file->size(); qint64 fileSize = file->size();
qDebug() << "[HttpClient] File size:" << fileSize;
QNetworkRequest request(url); QNetworkRequest request(url);
request.setHeader(QNetworkRequest::ContentTypeHeader, QStringLiteral("application/octet-stream")); request.setHeader(QNetworkRequest::ContentTypeHeader, QStringLiteral("application/octet-stream"));
@@ -154,14 +172,16 @@ void HttpClient::uploadFile(const Device& device, const QString& sessionId,
emit uploadProgress(sent, fileSize); emit uploadProgress(sent, fileSize);
}); });
connect(reply, &QNetworkReply::finished, this, [this, reply]() { connect(reply, &QNetworkReply::finished, this, [this, reply, filePath]() {
reply->deleteLater(); reply->deleteLater();
if (reply->error() != QNetworkReply::NoError) { if (reply->error() != QNetworkReply::NoError) {
qWarning() << "[HttpClient] uploadFile error:" << reply->errorString();
emit uploadError(reply->errorString()); emit uploadError(reply->errorString());
return; return;
} }
qDebug() << "[HttpClient] uploadFile completed:" << filePath;
emit uploadCompleted(); emit uploadCompleted();
}); });
} }

View File

@@ -156,6 +156,25 @@ QString SessionManager::createSendSession(const Device& target, const QMap<QStri
return sessionId; return sessionId;
} }
void SessionManager::setSendSessionTokens(const QString& sessionId, const QString& responseSessionId,
const QMap<QString, QString>& tokens)
{
if (!m_sendSessions.contains(sessionId)) {
return;
}
SendSession session = m_sendSessions.take(sessionId);
session.sessionId = responseSessionId;
for (auto it = tokens.constBegin(); it != tokens.constEnd(); ++it) {
if (session.files.contains(it.key())) {
session.files[it.key()].token = it.value();
}
}
m_sendSessions.insert(responseSessionId, session);
}
void SessionManager::startSendSession(const QString& sessionId) void SessionManager::startSendSession(const QString& sessionId)
{ {
if (!m_sendSessions.contains(sessionId)) { if (!m_sendSessions.contains(sessionId)) {