本文主要讲解关于网盘文件操作部分的分享文件的逻辑设计部分,主要步骤如下:
目录
1、实施步骤:
A、客户端发送分享文件请求(请求包含分享者、接收者、当前路径以及文件名)
那么PDU应该如何设置呢?分享者放在cadata里面,接收者放在camsg里面,当前路径也是camsg,那都放在一起了,如何做区分呢?将分享者和接收者的个数放在cadata里面,文件名也放在camsg或者将当前路径和文件名拼接,一起放在msg里面。
B、服务器端接收请求,对请求进行操作,并将操作结果返回给客户端
C、客户端接收回复信息并显示
2、代码实现
2.1、添加分享文件协议
ENUM_MSG_TYPE_SHARE_FILE_REQUEST, //分享文件请求
ENUM_MSG_TYPE_SHARE_FILE_RESPOND, //分享文件回复
2.2、添加取消槽函数
//添加分享文件槽函数
void cancleSelect();//取消选择
2.3、关联取消选择的槽函数
//关联取消选择信号槽
connect(m_pCancelSelectPB,SIGNAL(clicked(bool))
,this, SLOT(cancleSelect()));
2.4、添加取消槽函数的定义
void ShareFile::cancleSelect()
{
//获得选择的checkbox
QList<QAbstractButton*> cbList = m_pButtonGroup->buttons();
//循环遍历list
for(int i=0; i<cbList.size(); i++)
{
if(cbList[i]->isChecked())
{
cbList[i]->setChecked(false);
}
}
}
测试
点击取消选择
2.5、添加全选函数槽函数
void allSelect();//全部选择
2.6、关联全选槽函数
//关联全部选择信号槽
connect(m_pSelectAllPB,SIGNAL(clicked(bool))
,this, SLOT(allSelect()));
2.7、添加全部选择槽函数的定义
//分享文件全选
void ShareFile::allSelect()
{
//获得选择的checkbox
QList<QAbstractButton*> cbList = m_pButtonGroup->buttons();
//循环遍历list
for(int i=0; i<cbList.size(); i++)
{
if(!cbList[i]->isChecked())
{
cbList[i]->setChecked(true);
}
}
}
测试
2.8、确定取消分享按钮
void okShare(); //确定分享
void cancleShare();//取消分享
2.9、关联槽函数
//关联确定分享信号槽
connect(m_pOKPB,SIGNAL(clicked(bool))
,this, SLOT(okShare()));
//关联取消分享信号槽
connect(m_pCancelPB,SIGNAL(clicked(bool))
,this, SLOT(cancleShare()));
2.10、在共享文件函数部分获得文件名
void Book::shareFile()
{
//获得点击删除的文件
QListWidgetItem *pItem = m_pBookListW->currentItem();
//判断
if(NULL==pItem)
{
QMessageBox::warning(this,"分享文件","请选择分享的文件");
return;
}
else
{//获得分享的文件名
//文件名字
m_strShareFileName = pItem->text();
}
//获得好友列表
Friend *pFriend = OpeWidget::getInstance().getFriend();
QListWidget *pFriendList = pFriend->getFriendlist();
ShareFile::getinstance().updateFriend(pFriendList);
if(ShareFile::getinstance().isHidden())
{
ShareFile::getinstance().show();
}
}
2.11、添加确定分享文件的定义
//确定分享文件
void ShareFile::okShare()
{
//谁分享的
QString strName = TcpClient::getinstance().loginName();
//当前的路径
QString strCurPath = TcpClient::getinstance().curPath();
//获得共享的文件名
QString strShareFileName = OpeWidget::getInstance().getBook()->getShowFileName();
QString strPath = strCurPath +"/"+strShareFileName;
//获得接收者
//获得选择的checkbox
QList<QAbstractButton*> cbList = m_pButtonGroup->buttons();
int num =0;
//循环遍历list
for(int i=0; i<cbList.size(); i++)
{
if(cbList[i]->isChecked())
{
num++;
}
}
PDU *pdu = mkPDU(32*num+strPath.size()+1);
pdu->uiMsgType = ENUM_MSG_TYPE_SHARE_FILE_REQUEST;
sprintf(pdu->caData, "%s %d", strName.toStdString().c_str(),num);
int j =0;
for(int i=0;i<cbList.size();i++)
{
if(cbList[i]->isChecked())
{
memcpy((char*)(pdu->caMsg)+j*32, cbList[i]->text().toStdString().c_str(), cbList[i]->text().size());
j++;
}
}
//将路径拷贝进去
memcpy((char*)(pdu->caMsg)+num*32, strPath.toStdString().c_str(), strPath.size());
TcpClient::getinstance().getTcpSocket().write((char*)pdu, pdu->uiPDULen);
free(pdu);
pdu=NULL;
}
2.12、服务器端添加接收分享文件case
case ENUM_MSG_TYPE_SHARE_FILE_REQUEST:
{
char caSendName[32] = {'\0'};
int num = 0;
sscanf(pdu->caData, "%s%d", caSendName, &num);
int size = num*32;
PDU *respdu = mkPDU(pdu->uiMsgLen-size);
respdu->uiMsgType =ENUM_MSG_TYPE_SHARE_FILE_NOTE;
strcpy(respdu->caData,caSendName);
memcpy(respdu->caMsg, (char*)(pdu->caMsg)+size, pdu->uiMsgLen-size);
//通知给谁
char caReceName[32] = {'\0'};
for(int i=0;i<num;i++)
{
memcpy(caReceName, (char*)(pdu->caMsg)+i*32, 32);
MyTcpServer::getInstance().reSend(caReceName, respdu);
}
free(respdu);
respdu=NULL;
respdu=mkPDU(0);
respdu->uiMsgType = ENUM_MSG_TYPE_SHARE_FILE_RESPOND;
strcpy(respdu->caData, SHARE_FILE_OK);
write((char*)respdu, respdu->uiPDULen);
free(respdu);
respdu=NULL;
break;
}
2.13、在客户端添加通知信息的处理
//---------------------分享文件------------------------
case ENUM_MSG_TYPE_SHARE_FILE_RESPOND:
{
QMessageBox::information(this,"共享文件",pdu->caData);
break;
}
case ENUM_MSG_TYPE_SHARE_FILE_NOTE:
{
//是否接收对方共享的文件
char *pPath = new char[pdu->uiMsgLen];
memcpy(pPath, pdu->caMsg,pdu->uiMsgLen);
// //aa//bb/cc
char *pos = strrchr(pPath, '/');
qDebug()<<pos;
if(NULL != pos)
{//表示找到了
pos++;
QString strNote = QString("%1 share file->%2 \n Do you accept?").arg(pdu->caData).arg(pos);
int ret = QMessageBox::information(this,"共享文件",strNote);
if(QMessageBox::Yes==ret)
{
PDU *respdu = mkPDU(pdu->uiMsgLen);
respdu->uiMsgType =ENUM_MSG_TYPE_SHARE_FILE_NOTE_RESPOND;
memcpy(respdu->caMsg, pdu->caMsg,pdu->uiMsgLen);
//接收者名字
QString strName = TcpClient::getinstance().loginName();
strcpy(respdu->caData,strName.toStdString().c_str());
m_tcpSocket.write((char*)respdu, respdu->uiPDULen);
}
}
break;
}
2.14、服务器添加通知回复的case
case ENUM_MSG_TYPE_SHARE_FILE_NOTE_RESPOND:
{
QString strRecvPath = QString("./%1").arg(pdu->caData);
//共享者文件路径
QString strShareFilePath = QString("%1").arg((char*)(pdu->caMsg));
//拼接名字
int index = strShareFilePath.lastIndexOf('/');
QString strFileName = strShareFilePath.right(strShareFilePath.size()-index-1);
strRecvPath =strRecvPath +'/' +strFileName;
//拷贝文件
QFileInfo fileinfo(strShareFilePath);
if(fileinfo.isFile())
{
QFile::copy(strShareFilePath,strRecvPath);
}
else if(fileinfo.isDir())
{
}
break;
}
测试 登录jack和lucy这两个好友,刷新jack的文件,将test.txt文件发送给lucy,弹出窗口提示之后,刷新lucy文件,发现分享文件成功
成功
2.15、取消分享文件,先把它隐藏起来
//取消分享文件
void ShareFile::cancleShare()
{
hide();
}
2.16、文件夹的分享
//分享文件——文件夹的拷贝
void copyDir(QString strSrcDir, QString strDestDir);
2.17、添加定义
void MyTcpSocket::copyDir(QString strSrcDir, QString strDestDir)
{
//创建目标文件
QDir dir;
dir.mkdir(strDestDir);//产生一个目录
//打开原来要拷贝的目录
dir.setPath(strSrcDir);
QFileInfoList fileInfoList = dir.entryInfoList();
QString srcTmp;
QString destTmp;
//遍历list
for(int i=0;i<fileInfoList.size();i++)
{
if(fileInfoList[i].isFile())
{//如果是常规文件
qDebug()<<"filename:"<<fileInfoList[i].fileName();
srcTmp = strSrcDir + '/' +fileInfoList[i].fileName();
destTmp = strDestDir + '/' +fileInfoList[i].fileName();
QFile::copy(srcTmp,destTmp);
}
else if (fileInfoList[i].isDir()) {
if(QString(".") == fileInfoList[i].fileName()||QString("..") == fileInfoList[i].fileName())
{
continue;
}
srcTmp = strSrcDir + '/' +fileInfoList[i].fileName();
destTmp = strDestDir + '/' +fileInfoList[i].fileName();
copyDir(srcTmp,destTmp);//如果是子文件夹,递归进行拷贝
}
}
}
2.18、在case中调用
case ENUM_MSG_TYPE_SHARE_FILE_NOTE_RESPOND:
{
QString strRecvPath = QString("./%1").arg(pdu->caData);
//共享者文件路径
QString strShareFilePath = QString("%1").arg((char*)(pdu->caMsg));
//拼接名字
int index = strShareFilePath.lastIndexOf('/');
QString strFileName = strShareFilePath.right(strShareFilePath.size()-index-1);
strRecvPath =strRecvPath +'/' +strFileName;
//拷贝文件
QFileInfo fileinfo(strShareFilePath);
if(fileinfo.isFile())
{
QFile::copy(strShareFilePath,strRecvPath);
}
else if(fileinfo.isDir())
{
copyDir(strShareFilePath,strRecvPath);
}
break;
}
2.19、测试文件夹的分享
A、用户登录,刷新好友
B、点击图书,刷新文件,共享文件,选择Lucy好友,确定
C、点击yes
D、刷新lucy文件
E、查看文件是否真正创建
测试成功