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

您所在的位置:网站首页 基于json协议传输数据的软件 基于Qt实现的局域网上传文件和下载文件

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

2024-07-14 21:12| 来源: 网络整理| 查看: 265

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

先看下效果:

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

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

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

服务器端的关键代码:

//author:autumoon //联系QQ:4589968 //日期:2021-09-26 switch (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 #include #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 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; } }

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

欢迎交流与讨论!



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3