Files
frelay/ClientCore/FileTrans.cpp

481 lines
18 KiB
C++
Raw Permalink Normal View History

2025-06-16 23:41:35 +08:00
#include "FileTrans.h"
2025-06-18 14:53:56 +08:00
#include <QCoreApplication>
#include <QDir>
2025-06-18 13:18:31 +08:00
#include <QFileInfo>
2025-06-16 23:41:35 +08:00
FileTrans::FileTrans(ClientCore* clientCore) : clientCore_(clientCore)
{
RegisterSignal();
2025-06-18 14:53:56 +08:00
downTask_ = QSharedPointer<DoTransTask>::create();
sendTask_ = QSharedPointer<DoTransTask>::create();
2025-06-16 23:41:35 +08:00
}
2025-06-18 13:18:31 +08:00
/*
* When the local client actively sends a file, it cannot simultaneously perform download operations.
* Passive sending is an exception, primarily to monitor the sending progress. In contrast,
* the progress of passive sending is monitored by the requesting download side,
* so there is no need to track the progress locally.
*/
void FileTrans::ReqSendFile(const TransTask& task)
2025-06-16 23:41:35 +08:00
{
2025-10-20 16:40:52 +08:00
sendTask_->state = TaskState::STATE_RUNNING;
2025-06-18 13:18:31 +08:00
// TODO: check if running...
2025-06-20 13:03:27 +08:00
if (sendTask_->file.isOpen()) {
2025-11-05 23:09:37 +08:00
qWarning() << QString(tr("文件 [%1] 已经被打开,将会自动关闭。")).arg(sendTask_->file.fileName());
2025-10-20 16:40:52 +08:00
sendTask_->file.close();
2025-06-20 13:03:27 +08:00
}
2025-06-18 13:18:31 +08:00
// start
InfoMsg info;
info.toPath = task.remotePath;
info.fromPath = task.localPath;
2025-06-18 14:53:56 +08:00
sendTask_->file.setFileName(info.fromPath);
if (!sendTask_->file.open(QIODevice::ReadOnly)) {
2025-11-05 23:09:37 +08:00
qCritical() << QString(tr("打开 [%1] 失败。")).arg(info.fromPath);
2025-06-18 14:53:56 +08:00
sendTask_->state = TaskState::STATE_NONE;
return;
}
2025-06-18 13:18:31 +08:00
QFileInfo fileInfo(info.fromPath);
if (fileInfo.exists()) {
qint64 size = fileInfo.size();
if (size == 0) {
2025-11-05 23:09:37 +08:00
qCritical() << QString(tr("文件 [%1] 尺寸为0不会进行发送。")).arg(info.fromPath);
sendTask_->file.close();
sendTask_->state = TaskState::STATE_FINISH;
return;
}
2025-06-18 13:18:31 +08:00
info.permissions = static_cast<quint32>(fileInfo.permissions());
info.size = size;
} else {
2025-11-05 23:09:37 +08:00
qCritical() << QString(tr("文件 [%1] 不存在。")).arg(info.fromPath);
2025-06-18 14:53:56 +08:00
sendTask_->file.close();
2025-06-18 13:18:31 +08:00
return;
}
2025-06-18 14:53:56 +08:00
auto frame = clientCore_->GetBuffer(info, FBT_CLI_REQ_SEND, task.remoteId);
if (!ClientCore::syncInvoke(clientCore_, frame)) {
2025-11-05 23:09:37 +08:00
qCritical() << QString(tr("返回发送请求失败:%1")).arg(info.msg);
2025-06-18 14:53:56 +08:00
sendTask_->state = TaskState::STATE_NONE;
sendTask_->file.close();
2025-06-18 13:18:31 +08:00
return;
2025-06-18 14:53:56 +08:00
}
sendTask_->state = TaskState::STATE_RUNNING;
sendTask_->totalSize = info.size;
sendTask_->tranSize = 0;
2025-06-19 22:07:12 +08:00
sendTask_->task = task;
2025-06-18 13:18:31 +08:00
}
void FileTrans::ReqDownFile(const TransTask& task)
{
// start
InfoMsg info;
info.toPath = task.localPath;
info.fromPath = task.remotePath;
2025-06-20 09:45:39 +08:00
downTask_->task = task;
downTask_->totalSize = 0;
// recv
if (!Util::DirExist(info.toPath, false)) {
QDir dir;
if (!dir.mkpath(info.toPath)) {
info.msg = QString(tr("创建目录失败:%1")).arg(info.toPath);
qCritical() << info.msg;
auto f = clientCore_->GetBuffer(info, FBT_CLI_CANOT_SEND, task.remoteId);
if (!ClientCore::syncInvoke(clientCore_, f)) {
qCritical() << QString(tr("%1 回复 %2 失败。")).arg(info.msg, f->fid);
}
return;
}
qInfo() << QString(tr("目录 %1 不存在,已自动创建。")).arg(info.toPath);
}
2025-06-18 14:53:56 +08:00
downTask_->file.setFileName(Util::Get2FilePath(task.remotePath, task.localPath));
if (!downTask_->file.open(QIODevice::WriteOnly)) {
2025-11-05 23:09:37 +08:00
qCritical() << QString(tr("打开文件 [%1] 失败。")).arg(downTask_->file.fileName());
downTask_->state = TaskState::STATE_NONE;
return;
}
auto frame = clientCore_->GetBuffer(info, FBT_CLI_REQ_DOWN, task.remoteId);
if (!ClientCore::syncInvoke(clientCore_, frame)) {
2025-11-05 23:09:37 +08:00
qCritical() << QString(tr("返回发送请求失败:%1")).arg(info.msg);
2025-06-20 09:45:39 +08:00
downTask_->state = TaskState::STATE_NONE;
downTask_->file.close();
2025-06-18 13:18:31 +08:00
return;
}
2025-06-20 09:45:39 +08:00
downTask_->state = TaskState::STATE_RUNNING;
2025-06-18 13:18:31 +08:00
}
qint32 FileTrans::GetSendProgress()
{
2025-06-20 09:45:39 +08:00
if (sendTask_->state == TaskState::STATE_FINISH) {
2025-06-20 13:03:27 +08:00
sendTask_->state = TaskState::STATE_NONE;
2025-06-20 09:45:39 +08:00
return 100;
}
2025-06-18 14:53:56 +08:00
if (sendTask_->state != TaskState::STATE_RUNNING) {
2025-06-18 13:18:31 +08:00
return -1;
}
2025-06-20 13:03:27 +08:00
// wait file state ok.
2025-06-18 14:53:56 +08:00
double per = (sendTask_->tranSize * 100.0) / sendTask_->totalSize;
2025-06-20 13:03:27 +08:00
qint32 rt = static_cast<qint32>(per);
if (rt >= 100) {
return 99;
}
return rt;
2025-06-18 13:18:31 +08:00
}
qint32 FileTrans::GetDownProgress()
{
2025-06-20 09:45:39 +08:00
if (downTask_->state == TaskState::STATE_FINISH) {
2025-06-20 13:03:27 +08:00
downTask_->state = TaskState::STATE_NONE;
2025-06-20 09:45:39 +08:00
return 100;
}
2025-06-18 14:53:56 +08:00
if (downTask_->state != TaskState::STATE_RUNNING) {
2025-06-18 13:18:31 +08:00
return -1;
}
2025-06-20 09:45:39 +08:00
if (downTask_->totalSize == 0) {
return 0;
}
2025-06-20 13:03:27 +08:00
// wait file state ok.
2025-06-18 14:53:56 +08:00
double per = (downTask_->tranSize * 100.0) / downTask_->totalSize;
2025-06-20 13:03:27 +08:00
qint32 rt = static_cast<qint32>(per);
if (rt >= 100) {
return 99;
}
return rt;
2025-06-16 23:41:35 +08:00
}
void FileTrans::RegisterSignal()
2025-06-16 23:41:35 +08:00
{
connect(clientCore_, &ClientCore::sigReqSend, this, [this](QSharedPointer<FrameBuffer> frame) { fbtReqSend(frame); });
connect(clientCore_, &ClientCore::sigReqDown, this, [this](QSharedPointer<FrameBuffer> frame) { fbtReqDown(frame); });
connect(clientCore_, &ClientCore::sigTransDone, this, [this](QSharedPointer<FrameBuffer> frame) { fbtTransDone(frame); });
connect(clientCore_, &ClientCore::sigCanSend, this, [this](QSharedPointer<FrameBuffer> frame) { fbtCanSend(frame); });
connect(clientCore_, &ClientCore::sigCanotSend, this, [this](QSharedPointer<FrameBuffer> frame) { fbtCanotSend(frame); });
connect(clientCore_, &ClientCore::sigCanotDown, this, [this](QSharedPointer<FrameBuffer> frame) { fbtCanotDown(frame); });
connect(clientCore_, &ClientCore::sigCanDown, this, [this](QSharedPointer<FrameBuffer> frame) { fbtCanDown(frame); });
connect(clientCore_, &ClientCore::sigFileBuffer, this, [this](QSharedPointer<FrameBuffer> frame) { fbtFileBuffer(frame); });
2025-06-20 09:45:39 +08:00
connect(clientCore_, &ClientCore::sigFileInfo, this, [this](QSharedPointer<FrameBuffer> frame) { fbtFileInfo(frame); });
connect(clientCore_, &ClientCore::sigTransFailed, this, [this](QSharedPointer<FrameBuffer> frame) { fbtTransFailed(frame); });
2025-10-20 16:40:52 +08:00
connect(clientCore_, &ClientCore::sigOffline, this, [this](QSharedPointer<FrameBuffer> frame) { fbtInterrupt(frame); });
connect(clientCore_, &ClientCore::sigTransInterrupt, this,
[this](QSharedPointer<FrameBuffer> frame) { fbtInterrupt(frame); });
2025-06-16 23:41:35 +08:00
}
2025-06-17 16:42:39 +08:00
// The other party requests to send, prepare to receive.
2025-06-16 23:41:35 +08:00
void FileTrans::fbtReqSend(QSharedPointer<FrameBuffer> frame)
{
2025-06-17 16:42:39 +08:00
InfoMsg info = infoUnpack<InfoMsg>(frame->data);
2025-11-05 23:09:37 +08:00
qInfo() << QString(tr("%1 请求发送 %2 到 %3")).arg(frame->fid).arg(info.fromPath, info.toPath);
2025-06-17 11:48:13 +08:00
2025-06-17 16:42:39 +08:00
// judge is same client's same file.
2025-06-17 12:00:46 +08:00
2025-06-17 16:42:39 +08:00
// recv is single thread recv, judge idle
2025-06-18 14:53:56 +08:00
if (downTask_->state == TaskState::STATE_RUNNING) {
2025-11-05 23:09:37 +08:00
info.msg = QString(tr("繁忙......"));
auto f = clientCore_->GetBuffer(info, FBT_CLI_CANOT_SEND, frame->fid);
ClientCore::syncInvoke(clientCore_, f);
2025-06-17 11:48:13 +08:00
return;
}
// recv
if (!Util::DirExist(info.toPath, false)) {
QDir dir;
if (!dir.mkpath(info.toPath)) {
info.msg = QString(tr("创建目录失败:%1")).arg(info.toPath);
qCritical() << info.msg;
auto f = clientCore_->GetBuffer(info, FBT_CLI_CANOT_SEND, frame->fid);
if (!ClientCore::syncInvoke(clientCore_, f)) {
qCritical() << QString(tr("%1 回复 %2 失败。")).arg(info.msg, f->fid);
}
return;
}
qInfo() << QString(tr("目录 %1 不存在,已自动创建。")).arg(info.toPath);
}
2025-06-17 16:42:39 +08:00
auto newerPath = Util::Get2FilePath(info.fromPath, info.toPath);
2025-06-18 14:53:56 +08:00
downTask_->file.setFileName(newerPath);
if (!downTask_->file.open(QIODevice::WriteOnly)) {
2025-11-05 23:09:37 +08:00
info.msg = QString(tr("打卡文件失败: %1")).arg(newerPath);
2025-06-17 11:48:13 +08:00
qCritical() << info.msg;
auto f = clientCore_->GetBuffer(info, FBT_CLI_CANOT_SEND, frame->fid);
if (!ClientCore::syncInvoke(clientCore_, f)) {
qCritical() << QString(tr("打开接收文件 %1 失败,回复 %2 失败。")).arg(info.msg, f->fid);
2025-06-18 14:53:56 +08:00
downTask_->file.close();
2025-06-17 11:48:13 +08:00
}
return;
}
2025-06-17 16:42:39 +08:00
2025-06-18 14:53:56 +08:00
downTask_->totalSize = info.size;
downTask_->tranSize = 0;
downTask_->permission = info.permissions;
2025-06-17 16:42:39 +08:00
2025-11-05 23:09:37 +08:00
info.msg = QString(tr("打开待接收文件成功:%1")).arg(newerPath);
2025-06-19 22:31:34 +08:00
qInfo() << info.msg;
auto f = clientCore_->GetBuffer(info, FBT_CLI_CAN_SEND, frame->fid);
if (!ClientCore::syncInvoke(clientCore_, f)) {
2025-11-05 23:09:37 +08:00
qCritical() << QString(tr("打开接收文件 %1 成功, 但是回复 %2 失败。")).arg(info.msg, frame->fid);
2025-06-18 14:53:56 +08:00
downTask_->file.close();
2025-06-17 11:48:13 +08:00
return;
}
// 需要记录对方的ID,用于心跳检测
clientCore_->pushID(frame->fid);
2025-06-18 14:53:56 +08:00
downTask_->state = TaskState::STATE_RUNNING;
2025-06-17 11:48:13 +08:00
}
2025-06-17 16:42:39 +08:00
// The other party requests to download, prepare to send.
void FileTrans::fbtReqDown(QSharedPointer<FrameBuffer> frame)
{
InfoMsg info = infoUnpack<InfoMsg>(frame->data);
// send
auto doTask = QSharedPointer<DoTransTask>::create();
doTask->file.setFileName(info.fromPath);
if (!doTask->file.open(QIODevice::ReadOnly)) {
2025-11-05 23:09:37 +08:00
qCritical() << QString(tr("打开文件失败:%1")).arg(info.fromPath);
2025-06-17 16:42:39 +08:00
return;
}
2025-06-20 09:45:39 +08:00
QFileInfo fileInfo(info.fromPath);
if (fileInfo.exists()) {
qint64 size = fileInfo.size();
info.permissions = static_cast<quint32>(fileInfo.permissions());
info.size = size;
} else {
2025-11-05 23:09:37 +08:00
qCritical() << QString(tr("文件 [%1] 不存在。")).arg(info.fromPath);
2025-06-20 09:45:39 +08:00
doTask->file.close();
return;
}
// reply fileinfo
auto f = clientCore_->GetBuffer(info, FBT_CLI_FILE_INFO, frame->fid);
if (!ClientCore::syncInvoke(clientCore_, f)) {
2025-11-05 23:09:37 +08:00
qCritical() << QString(tr("发送 %1 信息失败。")).arg(info.fromPath);
2025-06-20 09:45:39 +08:00
doTask->file.close();
return;
}
2025-06-17 16:42:39 +08:00
doTask->task.isUpload = true;
doTask->task.localPath = info.fromPath;
doTask->task.remoteId = frame->fid;
// 需要记录对方的ID,用于心跳检测
clientCore_->pushID(frame->fid);
2025-06-17 16:42:39 +08:00
SendFile(doTask);
}
2025-06-17 11:48:13 +08:00
void FileTrans::fbtTransDone(QSharedPointer<FrameBuffer> frame)
{
auto info = infoUnpack<InfoMsg>(frame->data);
2025-06-18 14:53:56 +08:00
if (downTask_->file.isOpen()) {
2025-07-10 18:44:09 +08:00
downTask_->file.setPermissions(static_cast<QFileDevice::Permissions>(downTask_->permission));
2025-06-18 14:53:56 +08:00
downTask_->file.close();
downTask_->state = TaskState::STATE_FINISH;
2025-11-05 23:09:37 +08:00
info.msg = QString(tr("接收文件:%1 成功。")).arg(downTask_->file.fileName());
2025-06-19 22:31:34 +08:00
qInfo() << info.msg;
2025-06-17 11:48:13 +08:00
return;
}
2025-11-05 23:09:37 +08:00
qCritical() << QString(tr("成功收到了信号:%1 但是文件未打开。")).arg(info.msg);
2025-06-17 11:48:13 +08:00
}
2025-06-17 16:50:36 +08:00
// the other party indicates that can download, ready to receive the file.
2025-06-17 16:42:39 +08:00
void FileTrans::fbtCanDown(QSharedPointer<FrameBuffer> frame)
2025-06-17 11:48:13 +08:00
{
2025-06-17 16:50:36 +08:00
// ready to recv file.
auto info = infoUnpack<InfoMsg>(frame->data);
2025-06-18 14:53:56 +08:00
downTask_->permission = info.permissions;
downTask_->totalSize = info.size;
downTask_->tranSize = 0;
isSend_ = false;
2025-06-25 16:07:18 +08:00
qDebug() << QString(tr("Can Down trans file:%1.")).arg(info.fromPath);
2025-06-17 11:48:13 +08:00
}
2025-06-17 16:42:39 +08:00
void FileTrans::fbtCanotDown(QSharedPointer<FrameBuffer> frame)
2025-06-17 11:48:13 +08:00
{
InfoMsg info = infoUnpack<InfoMsg>(frame->data);
2025-11-05 23:09:37 +08:00
qCritical() << QString(tr("请求发送文件 %1 失败,原因:%2")).arg(info.fromPath, info.msg);
2025-06-17 11:48:13 +08:00
}
2025-06-17 16:42:39 +08:00
void FileTrans::fbtFileBuffer(QSharedPointer<FrameBuffer> frame)
2025-06-17 11:48:13 +08:00
{
2025-06-18 14:53:56 +08:00
if (downTask_->state != TaskState::STATE_RUNNING) {
2025-06-17 11:48:13 +08:00
return;
}
// For the sake of efficiency, not verify the legality of the file
2025-06-18 14:53:56 +08:00
auto ws = downTask_->file.write(frame->data.constData(), frame->data.size());
2025-06-17 11:48:13 +08:00
if (ws != frame->data.size()) {
2025-06-18 14:53:56 +08:00
downTask_->state = TaskState::STATE_FAILED;
2025-06-17 11:48:13 +08:00
InfoMsg info;
2025-06-18 14:53:56 +08:00
info.msg = downTask_->file.errorString();
auto f = clientCore_->GetBuffer(info, FBT_CLI_TRANS_FAILED, frame->fid);
ClientCore::syncInvoke(clientCore_, f);
2025-06-18 14:53:56 +08:00
downTask_->file.close();
2025-06-17 11:48:13 +08:00
}
2025-06-18 14:53:56 +08:00
downTask_->tranSize += ws;
2025-06-17 11:48:13 +08:00
}
2025-06-20 09:45:39 +08:00
void FileTrans::fbtFileInfo(QSharedPointer<FrameBuffer> frame)
{
InfoMsg info = infoUnpack<InfoMsg>(frame->data);
2025-11-05 23:09:37 +08:00
qInfo() << QString(tr("准备接收文件的大小:%1,权限:%2")).arg(info.size).arg(info.permissions);
2025-06-20 09:45:39 +08:00
downTask_->totalSize = info.size;
downTask_->tranSize = 0;
downTask_->permission = info.permissions;
}
2025-06-17 16:42:39 +08:00
void FileTrans::fbtCanotSend(QSharedPointer<FrameBuffer> frame)
2025-06-17 11:48:13 +08:00
{
2025-06-17 12:00:46 +08:00
InfoMsg info = infoUnpack<InfoMsg>(frame->data);
2025-11-05 23:09:37 +08:00
qCritical() << QString(tr("请求文件 %1 失败,原因:%2")).arg(info.fromPath, info.msg);
2025-06-18 14:53:56 +08:00
if (sendTask_->file.isOpen()) {
sendTask_->file.close();
}
2025-11-11 13:58:35 +08:00
sendTask_->state = TaskState::STATE_FAILED;
2025-06-17 11:48:13 +08:00
}
2025-06-17 16:42:39 +08:00
void FileTrans::fbtCanSend(QSharedPointer<FrameBuffer> frame)
2025-06-17 11:48:13 +08:00
{
2025-06-18 14:53:56 +08:00
InfoMsg info = infoUnpack<InfoMsg>(frame->data);
2025-11-05 23:09:37 +08:00
qInfo() << QString(tr("开始发送 %1 到 %2")).arg(info.fromPath, frame->fid);
isSend_ = true;
2025-06-18 14:53:56 +08:00
SendFile(sendTask_);
2025-06-17 11:48:13 +08:00
}
2025-06-17 16:42:39 +08:00
void FileTrans::fbtTransFailed(QSharedPointer<FrameBuffer> frame)
2025-06-17 11:48:13 +08:00
{
2025-11-05 23:09:37 +08:00
qCritical() << QString(tr("传输文件 %1 失败。")).arg(downTask_->file.fileName());
2025-06-18 14:53:56 +08:00
if (downTask_->file.isOpen()) {
downTask_->file.close();
2025-06-17 16:42:39 +08:00
}
2025-06-18 14:53:56 +08:00
downTask_->state = TaskState::STATE_FAILED;
2025-06-17 11:48:13 +08:00
}
void FileTrans::Interrupt(bool notic)
2025-10-20 16:40:52 +08:00
{
if (!isSend_ && downTask_->state == TaskState::STATE_RUNNING) {
2025-11-05 23:09:37 +08:00
qWarning() << QString(tr("传输文件 %1 中断。")).arg(downTask_->file.fileName());
downTask_->file.close();
if (notic) {
InfoMsg info;
info.msg = QString(tr("传输文件 %1 主动中断。")).arg(downTask_->file.fileName());
auto f = clientCore_->GetBuffer(info, FBT_CLI_TRANS_INTERRUPT, downTask_->task.remoteId);
if (!ClientCore::syncInvoke(clientCore_, f)) {
qCritical() << QString(tr("发送 %1 信息给 %2 失败。")).arg(info.msg).arg(downTask_->task.remoteId);
}
}
2025-10-20 16:40:52 +08:00
downTask_->state = TaskState::STATE_NONE;
}
if (isSend_ && sendTask_->state == TaskState::STATE_RUNNING) {
2025-11-05 23:09:37 +08:00
qWarning() << QString(tr("传输文件 %1 中断。")).arg(sendTask_->file.fileName());
sendTask_->file.close();
InfoMsg info;
info.msg = QString(tr("传输文件 %1 主动中断。")).arg(sendTask_->file.fileName());
auto f = clientCore_->GetBuffer(info, FBT_CLI_TRANS_INTERRUPT, sendTask_->task.remoteId);
if (!ClientCore::syncInvoke(clientCore_, f)) {
qCritical() << QString(tr("发送 %1 信息给 %2 失败。")).arg(info.msg).arg(sendTask_->task.remoteId);
}
2025-10-20 16:40:52 +08:00
sendTask_->state = TaskState::STATE_NONE;
}
}
void FileTrans::fbtInterrupt(QSharedPointer<FrameBuffer> frame)
{
Interrupt(false);
}
2025-06-17 11:48:13 +08:00
void FileTrans::SendFile(const QSharedPointer<DoTransTask>& task)
{
auto* sendThread = new SendThread(clientCore_);
sendThread->setTask(task);
connect(clientCore_, &ClientCore::sigFlowBack, sendThread, &SendThread::fbtFlowBack);
2025-06-17 11:48:13 +08:00
QMutexLocker locker(&sthMut_);
2025-06-18 13:18:31 +08:00
upTasks_[task->task.localId] = sendThread;
2026-03-24 22:25:00 +08:00
// 2026-03-24 找了一个可能卡顿的原因。
/*
Qt QThread类中start() run()
start()- 线 sendThread->start(); // ✅ 正确
线线 run()线 exec()
线/线
run()- sendThread->run(); // ❌ 错误用法
线线线 run()
/线
*/
// sendThread->run();
sendThread->start();
2025-06-17 11:48:13 +08:00
}
SendThread::SendThread(ClientCore* clientCore) : cliCore_(clientCore)
{
}
// 发送速度控制
void SendThread::fbtFlowBack(QSharedPointer<FrameBuffer> frame)
{
auto msg = infoUnpack<InfoMsg>(frame->data);
delay_ = msg.mark * BLOCK_LEVEL_MULTIPLE;
}
2025-06-17 11:48:13 +08:00
void SendThread::run()
{
// task's file shoule be already opened.
isSuccess_ = true;
delay_ = 0;
2025-06-25 16:07:18 +08:00
bool invokeSuccess = false;
2025-06-17 11:48:13 +08:00
while (!task_->file.atEnd()) {
2025-06-19 22:07:12 +08:00
auto frame = QSharedPointer<FrameBuffer>::create();
frame->tid = task_->task.remoteId;
frame->type = FBT_CLI_FILE_BUFFER;
2025-06-17 11:48:13 +08:00
frame->data.resize(CHUNK_BUF_SIZE);
2025-06-19 22:07:12 +08:00
2025-06-17 11:48:13 +08:00
auto br = task_->file.read(frame->data.data(), CHUNK_BUF_SIZE);
if (br == -1) {
2025-11-04 14:52:27 +08:00
qCritical() << QString(tr("读取失败: %1")).arg(task_->file.errorString());
isSuccess_ = false;
2025-06-17 11:48:13 +08:00
break;
}
frame->data.resize(br);
if (delay_ > 0) {
QThread::msleep(delay_);
}
2025-06-25 16:07:18 +08:00
invokeSuccess = QMetaObject::invokeMethod(cliCore_, "SendFrame", Qt::BlockingQueuedConnection,
Q_RETURN_ARG(bool, isSuccess_), Q_ARG(QSharedPointer<FrameBuffer>, frame));
if (!invokeSuccess || !isSuccess_) {
2025-11-04 14:52:27 +08:00
qCritical() << QString(tr("向 %1 发送失败.")).arg(task_->task.remoteId);
2025-06-17 11:48:13 +08:00
break;
}
2025-06-25 16:07:18 +08:00
task_->tranSize += frame->data.size();
// 关键点:这里不调用,无法中途收到别人发的数据。
2026-03-24 22:25:00 +08:00
// QCoreApplication::processEvents();
2025-06-17 11:48:13 +08:00
}
qInfo() << QString(tr("结束发送文件:%1")).arg(task_->file.fileName());
// 不是Open表示被别人关闭了,就不发送结束信号了。
if (task_->file.isOpen()) {
InfoMsg info;
auto f = cliCore_->GetBuffer(info, FBT_CLI_TRANS_DONE, task_->task.remoteId);
ClientCore::syncInvoke(cliCore_, f);
task_->file.close();
task_->state = TaskState::STATE_FINISH;
}
2025-06-17 11:48:13 +08:00
}
void SendThread::setTask(const QSharedPointer<DoTransTask>& task)
{
task_ = task;
}