作者:梦幻极光 http://ww.w.l.blog.163.com/blog/static/162589962007516103850603/
发送文件夹有很多方法,但是网上的代码很少,VC只有飞鸽有源代码,但是它采用的API的编程模式,不容易理解,加之注释又是日文或英文的,这样理解起来就更困难些.
有很多人在网上发帖子询问如何发送文件夹,有人回答:用Winraar压缩再传,说实话是个方法,但是是个很无聊的方法.还有人说先遍历文件,发现是目录就叫对方建立一个.这个也是个方法,但是有些复杂,尤其是目录又深又多,难免出错.
我要给大家介绍的方法是:
1.先传把文件目录和文件名都传过去;
2.处理文件目录以便建立.
3.传输文件夹.
首先,我们先定义一个结构体
struct FOLDERINFO
{
int fileLength; //记录文件长度
char fileName[128]; //记录文件名
char filePath[512] //记录文件路径
};
这里需要说明一下,为什么文件名,文件路径不用CString定义,原因是这个结构体我们要发给对方的,但是由于CString长度是不丁长的,导致结构体长度不能确定,从而使程序出错.
下面就是发送方的代码,我已经省去了目录选择和遍历目录的代码:
void CMyQQDlg::SendFiles()
{
CSocket sockClient;
sockClient.Create(); //创建Socket
CString ip;
m_You_IP.GetWindowText(ip); //m_You_IP是IP控件的变量
sockClient.Connect(ip, 11024); //
///
CString fileName; ///这是发送方处理目录的代码,如果没有这段代码
fileName=m_fileName; //将只能发送根目录下的文件:)
int a=fileName.Find(filepathone);
if(a!=2)
{
fileName=fileName.Right(fileName.GetLength()-a-1);
fileName="C:\\"+fileName;
}
CFile myFile;
FOLDERINFO myFileInfo;
if(!myFile.Open(m_fileName,CFile::modeRead|CFile::typeBinary))//m_fileName是遍历后得到的文件
return ;
myFileInfo.fileLength=myFile.GetLength(); //得到文件大小
strcpy(myFileInfo.fileName,myFile.GetFileName()); //得到文件名称
strcpy(myFileInfo.filePath,m_fileName);
sockClient.Send(&myFileInfo,sizeof(myFileInfo)); //发送文件信息
myFile.Seek(0,CFile::begin);
char m_buf[SIZEFILE]={0}; //缓冲区
CString strError;
int num=0;
int temp=0;
//开始发送
for(;;)
{
num=myFile.Read(m_buf, SIZEFILE);
if(num==0) break;
end=sockClient.Send(m_buf, num);
temp+=end;
}
myFile.Close();
sockClient.Close();
return ;
}
下面就是接收方的代码:
int CMyQQDlg::SaveYouFiles(CSocket &recSo, SOCKADDR_IN &client)
{
CString fnames;
CString filenamepath;
static int filescount=0;
CString strfileIp,strfileName,strfileLength;
char filemes[512]={0};//存文件名字的
int fileLengths=0;
FOLDERINFO myFileInfo;
recSo.Receive(&myFileInfo,sizeof(FOLDERINFO));
fileLengths=myFileInfo.fileLength;
strfileIp.Format(inet_ntoa(client.sin_addr));
strfileName.Format(myFileInfo.fileName); //得到文件名字
strfileLength.Format("%f",myFileInfo.fileLength/1024.0);
filenamepath.Format(myFileInfo.filePath); //得到文件路径
int a=filenamepath.ReverseFind(_T('\\'));//这5行代码是用来得到一个例如:\AMD\Intel\ATI\
filenamepath=filenamepath.Left(a+1); //主要是用来建立目录
CString b=filenamepath;
a=b.ReverseFind(_T(':'));
b=b.Right(b.GetLength()-a-1);
filenamepath="files"+b; //所有的文件都存在files文件夹下
CreateDirectory(filenamepath,NULL); //创建目录
strcpy(filemes,filenamepath+strfileName);
char bufs[SIZEFILE]={0}; //缓冲SIZEFILE=1024
CFile fs(filemes,CFile::modeCreate|CFile::modeWrite); //存文件
int n=0; //接受的字节数 0表示结束
int temp=0;
//开始接收
for(;;)
{
n=recSo.Receive(bufs,SIZEFILE); //接受
if(n==0) //0表示结束
break; //接受完毕
fs.Write(bufs,n);
// fputs(bufs,fp);
temp+=n;
}
fs.Close();
return 0;
}