www.pudn.com > DSPSample.rar > DSPFile.cpp


// DSPFile.cpp: implementation of the DSPFile class. 
// 
////////////////////////////////////////////////////////////////////// 
 
#include "stdafx.h" 
#include "DSPFile.h" 
 
#ifdef _DEBUG 
#undef THIS_FILE 
static char THIS_FILE[]=__FILE__; 
#define new DEBUG_NEW 
#endif 
 
////////////////////////////////////////////////////////////////////// 
// Construction/Destruction 
////////////////////////////////////////////////////////////////////// 
 
enum 
{ 
	SEND_SUCCESSFUL=100, 
	RECV_SUCCESSFUL, 
	SEND_TIMEOUT, 
	RECV_TIMEOUT, 
	SEND_FAIL, 
	RECV_FAIL, 
	SEND_ABORT, 
	RECV_ABORT, 
}; 
 
 
DSPFile::DSPFile() 
{ 
} 
 
DSPFile::~DSPFile() 
{ 
	if(this->m_ifs.is_open()) 
		this->m_ifs.close(); 
	if(this->m_ofs.is_open()) 
	{ 
		this->m_ofs.flush(); 
		this->m_ofs.close(); 
	} 
} 
 
bool DSPFile::Serialize(BYTE byClassLevels,BYTE byAttrNo,DSP::_DSPPACKET &dsp) 
{ 
	switch(byAttrNo) 
	{ 
		case 1: 
			dsp.Write(this->m_nFilesize); 
			return false; 
		case 2: 
			dsp.Write(this->m_strFilename); 
			return false; 
		case 3:						//序列化最后一个属性 
			if(this->m_ifs.is_open()==FALSE) 
			{ 
				//打开文件准备读 
				if(DSP::OpenIfstreamForRead(this->m_ifs,this->m_hFileDetail.strPathname)==FALSE) 
				{ 
					//如果打开文件失败 
					dsp.Write(NULL,0,true); 
					return true; 
				} 
			} 
			else 
			{ 
				//如果文件已经读完 
				this->m_ifs.close(); 
			} 
			dsp.Write(this->m_buff,FILE_SECT_SIZE,false); 
	} 
 
	return true; 
} 
 
bool DSPFile::UnSerialize(BYTE byClassLevels,BYTE byAttrNo,DSP::_DSPPACKET &dsp,DWORD dwLen) 
{ 
	//反序列化对象 
	switch(byAttrNo) 
	{ 
		case 1: 
			dsp.Read(this->m_nFilesize); 
			return false; 
		case 2: 
			dsp.Read(this->m_strFilename,dwLen); 
			return false; 
		case 3:						//序列化最后一个属性 
			if(this->m_ofs.is_open()==FALSE) 
			{ 
				this->m_hFileDetail.strPathname	=this->m_strFilename.c_str(); 
				this->m_hFileDetail.nFilesize	=this->m_nFilesize; 
				this->m_hFileDetail.nCurrLen	=FILE_SECT_SIZE; 
 
				//传送文件名和尺寸,并且打开文件输出流,准备写 
				::SendMessage(this->m_hFileDetail.hwnd,MSG_SETFILENAMESIZE, 
										(WPARAM)&this->m_hFileDetail,0); 
 
				//打开对话框,选择被保存的文件名 
				CFileDialog fileDialog(FALSE,NULL,this->m_strFilename.c_str(),OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT); 
				if(fileDialog.DoModal()==IDOK) 
				{ 
					//得到被选择的文件名 
					this->m_hFileDetail.strPathname	=fileDialog.GetPathName(); 
					//重新传送文件名和尺寸 
					::SendMessage(this->m_hFileDetail.hwnd,MSG_SETFILENAMESIZE, 
										(WPARAM)&this->m_hFileDetail,0); 
 
					this->m_hFileDetail.nCurrLen	=0; 
 
					if(DSP::OpenOfstreamForWrite(this->m_ofs,this->m_hFileDetail.strPathname)==FALSE) 
					{ 
						//如果找开文件失败 
						dsp.Read(NULL,0); 
						return true; 
					} 
				} 
				else 
				{ 
					dsp.Read(NULL,0); 
					return true; 
				} 
			} 
			else 
			{ 
				//文件已经写完 
				this->m_ofs.flush(); 
				this->m_ofs.close(); 
			} 
			dsp.Read(this->m_buff,dwLen); 
	} 
 
	return true; 
} 
 
bool DSPFile::AttrSectRecv(BYTE byClassLevels,BYTE byAttrNo,const char* const lpBuff,DWORD dwLen,bool bLast) 
{ 
	this->m_ofs.write(lpBuff,dwLen); 
	this->m_hFileDetail.nCurrLen	+=dwLen; 
	::SendMessage(this->m_hFileDetail.hwnd,MSG_RECVSECT,(WPARAM)&this->m_hFileDetail,dwLen); 
	return true; 
} 
 
bool DSPFile::AttrSectSend(BYTE byClassLevels,BYTE byAttrNo,char** const lpBuff,DWORD& dwLen,bool& bContinue) 
{ 
	this->m_ifs.read(*lpBuff,dwLen); 
	if(this->m_ifs.eof()) 
	{ 
		//如果文件已经结束 
		//得到文件的大小 
		int size	=this->m_ifs.tellg(); 
 
		//得到最后读取的文件尺寸,设定最后接收的字节数 
		dwLen		=size%dwLen; 
 
		//设定不需要再继续接收 
		bContinue	=false; 
	} 
	this->m_hFileDetail.nCurrLen	+=dwLen; 
	::SendMessage(this->m_hFileDetail.hwnd,MSG_SENDSECT,(WPARAM)&this->m_hFileDetail,dwLen); 
	return true; 
} 
 
bool DSPFile::ReadySendFile(bool& bRun,SOCKET sock,bool bCrc,DSP::_DSPPACKET& packet,HWND hWnd)  
{ 
	// TODO: Add your control notification handler code here 
	//开始传送文件线程 
	CFileDialog fileDialog(TRUE,NULL,NULL,OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT|OFN_FILEMUSTEXIST); 
	if(fileDialog.DoModal()==IDOK) 
	{ 
		//得到被选择的包含路径的文件名 
		this->m_hFileDetail.strPathname	=fileDialog.GetPathName(); 
 
		//得到被选择的文件名 
		this->m_strFilename				=fileDialog.GetFileName(); 
 
		//得到文件的大小 
		HANDLE	fileHandle	=::CreateFile(this->m_hFileDetail.strPathname,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,0,NULL); 
		this->m_nFilesize	=::GetFileSize(fileHandle,NULL); 
		::CloseHandle(fileHandle); 
 
		//保存文件尺寸到结构中 
		this->m_hFileDetail.nFilesize	=this->m_nFilesize; 
 
		//初始化传送文件的步长 
		this->m_hFileDetail.nCurrLen	=FILE_SECT_SIZE; 
 
		//初始化值 
		this->m_hFileDetail.hwnd		=hWnd; 
		this->m_hFileDetail.lpbRun		=&bRun; 
		bRun							=true; 
 
		//通知准备传送的文件名和尺寸 
		::SendMessage(this->m_hFileDetail.hwnd,MSG_SETFILENAMESIZE,(WPARAM)&this->m_hFileDetail,0); 
 
		//初始化传送文件的尺寸 
		this->m_hFileDetail.nCurrLen	=0; 
 
		//设置等待时间为10分钟 
		packet.Timeout.tv_sec			=600; 
		packet.SetParameter(FALSE,bCrc); 
 
		//序列化对象 
		if(packet.WriteObject(sock,*this)) 
		{ 
			//传送完成 
			::SendMessage(this->m_hFileDetail.hwnd,MSG_SENDCOMPLETE,(WPARAM)&this->m_hFileDetail,SEND_SUCCESSFUL); 
			return true; 
		} 
		else 
		{ 
			if(bRun) 
			{ 
				//传送失败,可能是对方放弃或传送失败或超时 
				DSP::_DSPERROR* lphErr	=packet.GetLastError(); 
 
				::SendMessage(this->m_hFileDetail.hwnd,MSG_SENDCOMPLETE,(WPARAM)&this->m_hFileDetail, 
					(lphErr->nErrorNo==DSP::ERR_SEND_HEADER)?SEND_TIMEOUT:SEND_FAIL); 
			} 
			else 
			{ 
				//如果是点击了放弃按钮 
				::SendMessage(this->m_hFileDetail.hwnd,MSG_SENDCOMPLETE,(WPARAM)&this->m_hFileDetail,SEND_ABORT); 
			} 
		} 
	} 
	return false; 
} 
 
bool DSPFile::ReadyRecvFile(bool& bRun,SOCKET sock,DSP::_DSPPACKET& packet,HWND hWnd) 
{ 
	//设置放充的布尔变量,改变该变量的值,可以立即中止传送,初始化为允许接收 
	bRun						=true; 
	this->m_hFileDetail.lpbRun	=&bRun; 
 
	//设置进行消息传递的窗体的句柄 
	this->m_hFileDetail.hwnd	=hWnd; 
	 
	while(true) 
	{ 
		if(packet.ReadObject(sock,this)) 
		{ 
			//接收完成 
			::SendMessage(this->m_hFileDetail.hwnd,MSG_SENDCOMPLETE,(WPARAM)&this->m_hFileDetail,RECV_SUCCESSFUL); 
		} 
		else 
		{ 
			if(bRun) 
			{ 
				//接收失败,可能是对方放弃或接收数据时失败或超时 
				DSP::_DSPERROR* lphErr	=packet.GetLastError(); 
 
				::SendMessage(this->m_hFileDetail.hwnd,MSG_SENDCOMPLETE,(WPARAM)&this->m_hFileDetail, 
					(lphErr->nErrorNo==DSP::ERR_RECV_HEADER)?RECV_TIMEOUT:RECV_FAIL); 
			} 
			else 
			{ 
				//如果是接收被放弃 
				::SendMessage(this->m_hFileDetail.hwnd,MSG_SENDCOMPLETE,(WPARAM)&this->m_hFileDetail,RECV_ABORT); 
			} 
			return false; 
		} 
	} 
} 
 
bool DSPFile::GetCompleteInfo(int which, CString &str) 
{ 
	switch(which) 
	{ 
		case SEND_SUCCESSFUL: 
			str	="传送文件成功!"; 
			return true; 
		case RECV_SUCCESSFUL: 
			str	="接收文件成功!"; 
			return true; 
		case SEND_TIMEOUT: 
			str	="传送文件超时或对方关闭了连接!"; 
			break; 
		case RECV_TIMEOUT: 
			str	="接收文件超时或对方关闭了连接!"; 
			break; 
		case SEND_FAIL: 
			str	="传送文件失败,可能是连接被中断或超时!"; 
			break; 
		case RECV_FAIL: 
			str	="接收文件失败,可能是连接被中断或超时,或接收到了不正确的信息!"; 
			break; 
		case SEND_ABORT: 
			str	="传送文件过程被中止!"; 
			break; 
		case RECV_ABORT: 
			str	="接收文件过程被中止!"; 
			break; 
	} 
	return false; 
}