基于Qt实现的局域网上传文件和下载文件

news/2024/11/29 5:32:12/

应某C友要求,写了这个局域网同步小工具,说是同步,实际上只是实现了文件的上传和下载,操作都在客户端,服务端只需要配置好同步目录就不用管了。

先看下效果:

 工具的实现非常简单,实际上就是基于QTcp互相发送文件,那么主要问题就是,如何在客户端点击下载的时候,通知服务器传送数据给客户端,而这个就需要用到GitHub的一个轻量级开源库JQLibrary,这个库对于轻量级请求完全够用,非常感谢原作者的分享。

服务器配置文件,配置好同步目录即可:

 其中nCmdPort为命令端口,nTransPort为传送文件的端口,可以任意指定,保持一致即可。

服务器端的关键代码:

//author:autumoon
//联系QQ:4589968
//日期:2021-09-26switch (nFun){case enCheckState :{//实际只使用了两个目录,这里取qMin是为了防止配置文件错误int nLocalSavePathCount = qMin(cfg_server.lLocalSavePaths.size(), 2);if (nLocalSavePathCount >= 1 ){lKeys.push_back("ip");lKeys.push_back("state");lKeys.push_back("root");lValues.push_back(strIp);lValues.push_back("OK");lValues.push_back(cfg_server.lLocalSavePaths[0]);//进一步判断,目录是否可写,剩余空间for (int j = 0; j < nLocalSavePathCount; ++j){CStdDir::createDirectory(cfg_server.lLocalSavePaths[j]);}}QByteArray cfgData = JsonParser::StringList2ByteArray(lKeys, lValues);//执行完毕session->replyBytes(cfgData);bAlreadyReply = true;break;}case enCheckClientReady:{bool bRes = false;if (g_pDlg){bRes = !g_pDlg->IsClientBusy();}//返回执行结果session->replyJsonObject({{"ready", QString::number(bRes).toUtf8().data()}});bAlreadyReply = true;break;}case enSyncDir:{//返回执行结果,防止再次发送请求QString strReturnInfo = "1";QString strClientSycDir, strTransPort;if (g_pDlg && JsonParser::ParseRootKeyValue(ba, "dir", strClientSycDir) == 0&& JsonParser::ParseRootKeyValue(ba, "port", strTransPort) == 0){emit g_pDlg->start_download(strClientSycDir, strIp, strTransPort.toUInt());//g_pDlg->SendToClient(strClientSycDir, strIp, strTransPort.toUInt());}session->replyJsonObject({{"state", strReturnInfo.toUtf8().data()}});bAlreadyReply = true;break;}default:break;}}

这里就不得不说一下流程,首先客户端必须连接到服务端,同时请求服务端的配置文件内容,获取服务器端共享的目录,方便后续上传和下载。

而上传和下载的过程中自然需要注意服务器是否繁忙,所以在传输之前都需要检查服务器状态。

最后就是数据传输了,用我以前写好的传输类,很快就完成了!

客户端界面:

 

客户端主要代码:

#include "mainwindow.h"
#include "ui_mainwindow.h"//author:autumoon
//联系QQ:4589968
//日期:2021-09-24
#include "QtDirFile.h"
#include "TcpUploadClient.h"
#include "scanservercfg.h"
#include <QMessageBox>
#include <QNetworkInterface>
#include "Log.h"MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);//读取配置文件QString strConfigPath = GetConfigPath();if (QFile::exists(strConfigPath)){//读取ReadConfigFile(strConfigPath, m_cfg);}else{WriteConfigFile(strConfigPath, m_cfg);}ui->le_synDir->setText(m_cfg.strShareRoot);ui->pb_progress->setValue(0);//需要向服务器发送请求,获取服务器的保存路径ScanServerCfg* ssc = new ScanServerCfg(this);connect(ssc, SIGNAL(finished(bool, QString)), this , SLOT(get_server_cfg(bool, QString)));ssc->CheckState(m_cfg.strServerIp, m_cfg.nCmdPort);//需要启动一个下载的server//初始化bLocalServer = false;m_server = nullptr;if (m_server == nullptr){m_server = new TcpUploadServer(this);connect(m_server, SIGNAL(progress(qint64, qint64)), this, SLOT(download_progress(qint64, qint64)));m_server->SetPort(m_cfg.nTransPort);if(m_server->StartServer()){bLocalServer = true;CLOG::Out("本地用于下载的服务启动成功!");}else{bLocalServer = false;CLOG::Out("本地用于下载的服务启动失败!");}}
}MainWindow::~MainWindow()
{delete ui;
}void MainWindow::on_btn_upload_clicked()
{QString strIp = m_cfg.strServerIp;QString strSaveDir = m_strSaveDir;QString strSrcDir = ui->le_synDir->text();if(strSrcDir.length() == 0 || strSaveDir.length() == 0 || strIp.length() == 0){return;}if(!ScanServerCfg::CheckIsServerReady(m_cfg.strServerIp, m_cfg.nCmdPort)){QMessageBox::warning(this, "忙碌!", "服务器忙碌,请稍后再试!");return;}TcpUploadClient *tuc = new TcpUploadClient(this);connect(tuc, SIGNAL(progress(qint64, qint64, const QString&)), this, SLOT(show_progress(qint64, qint64, const QString&)));tuc->SetHostAndPort(strIp,  m_cfg.nTransPort);tuc->SetLableStatus(ui->lb_state);QStringList lSrcFiles, lDstFiles;int n = QTDirFile::getFiles(strSrcDir, lSrcFiles);for (int i = 0; i < n; ++i){//得到目标路径QString strCurFile = lSrcFiles[i];QString strDstFile = strCurFile;strDstFile.replace(strSrcDir, strSaveDir);lDstFiles.push_back(strDstFile);}tuc->StartUpload(lSrcFiles, lDstFiles);
}void MainWindow::on_btn_browse_clicked()
{QString strDir = QTDirFile::BrowseDir();if (strDir.length()){ui->le_synDir->setText(strDir);}
}void MainWindow::get_server_cfg(bool bRet, QString strServerSyncDir)
{m_strSaveDir = bRet ? strServerSyncDir : "";if(bRet){m_strSaveDir = strServerSyncDir;ui->lb_state->setText("连接服务器成功!");}else{ui->lb_state->setText("连接服务器失败!");}
}void MainWindow::download_progress(qint64 cur, qint64 sum)
{ui->pb_progress->setValue(cur);ui->pb_progress->setMaximum(sum);
}void MainWindow::show_progress(qint64 cur, qint64 sum, const QString & info)
{ui->pb_progress->setValue(cur);ui->pb_progress->setMaximum(sum);ui->pb_progress->setToolTip(info);
}QHostAddress MainWindow::getLocalHostIP()
{QList<QHostAddress> AddressList = QNetworkInterface::allAddresses();QHostAddress result;foreach(QHostAddress address, AddressList){if(address.protocol() == QAbstractSocket::IPv4Protocol &&address != QHostAddress::Null &&address != QHostAddress::LocalHost){if (address.toString().contains("127.0.")){continue;}result = address;break;}}return result;
}void MainWindow::on_btn_download_clicked()
{if(!ScanServerCfg::CheckIsServerReady(m_cfg.strServerIp, m_cfg.nCmdPort)){QMessageBox::warning(this, "忙碌!", "服务器忙碌,请稍后再试!");return;}if (!bLocalServer){QMessageBox::critical(this, "失败!", "本地用于下载的服务启动失败!");return;}if (!ScanServerCfg::StartDownload(m_cfg.strServerIp , MainWindow::getLocalHostIP().toString(), m_cfg.nCmdPort, m_cfg.nTransPort, m_cfg.strShareRoot)){QMessageBox::critical(this, "错误", "下载出错!");return;}
}

总的来说,虽然功能容易实现,但是细节要注意的还是挺多的,最后基本功能实现了,但是要使得小工具好用肯定还得有一些细节需要完善的!

欢迎交流与讨论!


http://www.ppmy.cn/news/798261.html

相关文章

ArcGIS 利用全局(局域)空间自相关分析进行城市不同家庭收入情况的空间集聚分析

空间自相关指的是分布于不同空间位置的地理事物&#xff0c;它的某一个属性值存在统计相关性&#xff0c;一般来说&#xff0c;距离越近&#xff0c;相关性越大。 本次分析某一个城市的不同收入家庭的居住空间分布情况。 先用全局空间自相关指数&#xff08;Moran’s指数&…

ensp模拟器构建局域网络与使用模拟器接入互联网

实战案例——使用模拟器构建局域网络 &#xff08;1&#xff09;需求分析 本实验的目的在于建立小型局域网。由于公司由不同部门组成&#xff0c;并分布在不同地点&#xff0c;因此需要划分不同网络实现互联互通。设计以下网络&#xff1a;两个部门各使用一台交换机连接&#x…

4.7.2 在局域网上进行硬件多播

IANA提供的以太网多播地址的范围是&#xff1a;01-00-5E-00-00-00 到 01-00-5E-7F-FF-FF 只有 23位 能用作 多播地址 之前在分类ip地址中介绍过D类地址 FX . XX . XX . XX 是多播地址&#xff0c;有28位能用 因 多播ip地址 与 以太网多播地址 的映射关系不是唯一的&#xff0c;…

GIS原理学习——栅格数据的局域分析、领域分析及分区运算

文章目录 个人小总结&#xff1a;详细归纳&#xff1a;单一栅格运算多个栅格运算邻域分析分区运算 个人小总结&#xff1a; 局域分析可用于单层面栅格数据叠合分析和多层面栅格数据叠合分析。 多层面栅格数据叠合分析&#xff0c;又称为像元统计&#xff0c;常以栅格像元为单位…

非局域均值去噪

http://www.cnblogs.com/luo-peng/p/4785922.html 非局部均值&#xff08;NL-means&#xff09;是近年来提出的一项新型的去噪技术。该方法充分利用了图像中的冗余信息&#xff0c;在去噪的同时能最大程度地保持图像的细节特征。基本思想是&#xff1a;当前像素的估计值由图像中…

局域网络设计方案

&#xfeff;&#xfeff; 绪论 一、前言 二十一世纪是知识经济时代。随着现代科学技术的飞速发展&#xff0c;全球信息化浪潮势不可挡&#xff0c;已经迅速延伸至国防、科研、经济、教育等各个领域&#xff0c;也不可避免地改变着传统的企业人事的工作模式&#xff0c;利用当…

基于RBF和小波变换的局域波法

1.气缸盖压振动是多种激励力作用的结果&#xff0c;由于各个激励力的时间间隔性&#xff0c;可以通过时域加窗来提取缸盖有气缸压力引起的振动响应信号。 2.时域统计平均技术&#xff1a;从混有噪声干扰的信号中提取有用信号的技术。 3.平滑处理 4.等曲柄转角化和信号重采样…

vasp-电荷局域密度图(ELF)

以Graphene为例&#xff1a; INCAR: 添加LELF .TRUE. SYSTEM graphene ISTART 0 ICHARG 2 #Startparameter for this run: PREC A #Electronic Relaxation ENCUT 500 NELM 60 NELMIN 6 NELMDL -12 …