mfc采用内存映射复制文件

基本数据类:(复制文件过程中用到的基本数据类)
.h文件:

#pragma once

//上传/下载信息
struct SUpload_DownloadInfo
{
	SUpload_DownloadInfo(CString strFilePath = _T(""), CString strCenterPath = _T(""), GUID guidDev = GUID_NULL);
	CString			m_strFilePath;			//本地路径
	CString			m_strCenterPath;		//中央存储路径
	__int64			m_nFileSize;
	BOOL			m_bUploaded;			//是否已经上载完成
	float			m_fUploadProgress;		//上载进度

	GUID			m_guidDev;				//下发设备ID
	BOOL			m_bMainDownloading;		//主机下发中
	BOOL			m_bMainDownloaded;		//主机是否已经下发完成
	float			m_fMainDownloadProgress;//主机下发进度
	BOOL			m_bBackDownloading;		//备机下发中
	BOOL			m_bBackDownloaded;		//备机是否已经下发完成
	float			m_fBackDownloadProgress;//备机下发进度
};
typedef CArray<SUpload_DownloadInfo*, SUpload_DownloadInfo*> ArUpload_DownloadInfo;

SUpload_DownloadInfo*G_FindUploadDownloadInfo(ArUpload_DownloadInfo& arInfo, CString const& strCenterPath, GUID const&guidDev);

//文件复制信息
struct SFileCopyInfo
{
	SFileCopyInfo(CString strFileSour = _T(""), CString strFileDes = _T(""));
	SFileCopyInfo(SFileCopyInfo* pFileCopyInfo);

	CString		strFileSour;	//源文件路径
	CString		strFileDes;		//目标文件路径
};
typedef	CArray<SFileCopyInfo, SFileCopyInfo> ArFileCopyInfo;
typedef	CArray<SFileCopyInfo*, SFileCopyInfo*> ArPtrFileCopyInfo;


struct SMD5FileInfo
{
	friend CArchive & operator << (CArchive & ar, SMD5FileInfo const& sMD5FileInfo);
	friend CArchive & operator >> (CArchive & ar, SMD5FileInfo& sMD5FileInfo);
	

	SMD5FileInfo(CString strFilePath = _T(""), CTime tCreate = 0, CTime tModity = 0, __int64 nSize = 0);
	SMD5FileInfo(SMD5FileInfo const& sMD5FileInfo);
	~SMD5FileInfo();
	SMD5FileInfo & operator = (const SMD5FileInfo& sMD5FileInfo);

	CTime		StringToTime(CString strTime);

	CString		strFilePath;
	int			nFileType;	//文件类型

	CTime		tCreate;	//创建时间		
	CTime		tModity;	//修改时间
	__int64		nSize;		//长度

	__int64		nSizeLoaded;//完成的长度

	int			nWidth;		//宽度
	int			nHeight;	//高度

	long		lDuration;	//视频的长度
	float		fFrameRate;	//帧率
	__int64		nCodeRate;	//码率

	CNCBuffer*	pBuffer;	//预览图
};
typedef CArray<SMD5FileInfo*, SMD5FileInfo*> ArMD5FileInfo;

//文件夹信息
struct SFolderInfo
{
	SFolderInfo(CString strFolderPath = _T(""))
	{
		this->strFolderPath = strFolderPath;
		arMD5FileInfo.SetSize(0);
		bLoadEnd = FALSE;
	}
	CString			strFolderPath;
	ArMD5FileInfo	arMD5FileInfo;
	BOOL			bLoadEnd;
};
typedef CArray<SFolderInfo*, SFolderInfo*> ArFolderInfo;


CString				G_GetMD5FileName(CString strName, BOOL bLoadEnd = FALSE);
__int64				G_GetFileSize(CString strFilePath);
BOOL				G_IsFileInfoSame(SMD5FileInfo* pFileInfoSour, SMD5FileInfo* pFileInfoDes);
//获取文件信息
VOID				G_GetFileInfo(CString strFilePath, SMD5FileInfo& sMD5FileInfo, int nWidth = 80, int nHeight = 45);
//获取MD5文件信息(.md文件,下载完成的md5文件)
VOID				G_GetMd5FileInfo_Complete(CString strFilePath, SMD5FileInfo& sMD5FileInfo);//.md
//获取MD5文件信息(.md.back文件,下载中的md5文件)
VOID				G_GetMd5FileInfo_Loading(CString strFilePath, SMD5FileInfo& sMD5FileInfo);//.md.back
//获取文件属性信息
VOID				G_GetFileStatus(CString strFilePayh, SMD5FileInfo& sFileInfo);
//根据资源路径获取MD5信息
SMD5FileInfo*		G_GetMd5FileInfoByResPath(CString strFilePath);

.cpp文件:

#include "stdafx.h"
#include "Upload_DownloadInfo.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

///SUpload_DownloadInfo///
SUpload_DownloadInfo::SUpload_DownloadInfo(CString strFilePath /*= _T("")*/, CString strCenterPath /*= _T("")*/, GUID guidDev /*= GUID_NULL*/)
{
	m_strFilePath = strFilePath;
	m_strCenterPath = strCenterPath;
	m_nFileSize = 0;
	m_guidDev = guidDev;
	m_bUploaded = FALSE;
	m_fUploadProgress = 0.0f;
	m_bMainDownloading = FALSE;
	m_bMainDownloaded = FALSE;
	m_fMainDownloadProgress = 0.0f;
	m_bBackDownloading = FALSE;
	m_bBackDownloaded = FALSE;
	m_fBackDownloadProgress = 0.0f;
}

SUpload_DownloadInfo*G_FindUploadDownloadInfo(ArUpload_DownloadInfo& arInfo, CString const& strCenterPath, GUID const&guidDev)
{
	SUpload_DownloadInfo*pInfo = NULL;
	int i, nSize = (int)arInfo.GetSize();
	for (i = 0; i < nSize; i++)
	{
		pInfo = arInfo[i];
		if (pInfo->m_guidDev == guidDev && pInfo->m_strCenterPath.CompareNoCase(strCenterPath) == 0)
			return pInfo;
	}
	return NULL;
}


///SFileCopyInfo///
SFileCopyInfo::SFileCopyInfo(CString strFileSour /*= _T("")*/, CString strFileDes /*= _T("")*/)
{
	this->strFileSour = strFileSour;
	this->strFileDes = strFileDes;
}

SFileCopyInfo::SFileCopyInfo(SFileCopyInfo* pFileCopyInfo)
{
	if (pFileCopyInfo == NULL)
		return;

	this->strFileSour = pFileCopyInfo->strFileSour;
	this->strFileDes = pFileCopyInfo->strFileDes;
}

/SFileInfo/
CArchive & operator << (CArchive & ar, SMD5FileInfo const& sMD5FileInfo)
{
	DWORD dwVersion = 0;
	ar << dwVersion;
	ar << sMD5FileInfo.strFilePath;
	ar << sMD5FileInfo.nFileType;
	ar << sMD5FileInfo.tCreate;
	ar << sMD5FileInfo.tModity;
	ar << sMD5FileInfo.nSize;
	ar << sMD5FileInfo.nSizeLoaded;
	ar << sMD5FileInfo.nWidth;
	ar << sMD5FileInfo.nHeight;
	ar << sMD5FileInfo.lDuration;
	ar << sMD5FileInfo.fFrameRate;
	ar << sMD5FileInfo.nCodeRate;
	BOOL bBuffer = sMD5FileInfo.pBuffer != NULL ? TRUE : FALSE;
	ar << bBuffer;
	if (sMD5FileInfo.pBuffer != NULL)
	{
		ar << sMD5FileInfo.pBuffer->m_nWidth;
		ar << sMD5FileInfo.pBuffer->m_nHeight;
		ar.Write(sMD5FileInfo.pBuffer->m_pBuffer, sMD5FileInfo.pBuffer->m_nWidth * sMD5FileInfo.pBuffer->m_nHeight * sizeof(DWORD));
	}
	return ar;
}

CArchive & operator >> (CArchive & ar, SMD5FileInfo& sMD5FileInfo)
{
	DWORD dwVersion = 0;
	ar >> dwVersion;
	ar >> sMD5FileInfo.strFilePath;
	ar >> sMD5FileInfo.nFileType;
	ar >> sMD5FileInfo.tCreate;
	ar >> sMD5FileInfo.tModity;
	ar >> sMD5FileInfo.nSize;
	ar >> sMD5FileInfo.nSizeLoaded;
	ar >> sMD5FileInfo.nWidth;
	ar >> sMD5FileInfo.nHeight;
	ar >> sMD5FileInfo.lDuration;
	ar >> sMD5FileInfo.fFrameRate;
	ar >> sMD5FileInfo.nCodeRate;
	DeletePtr(sMD5FileInfo.pBuffer);
	BOOL bBuffer = FALSE;
	ar >> bBuffer;
	if (bBuffer)
	{
		int nWidth = 0, nHeight = 0;
		ar >> nWidth;
		ar >> nHeight;
		sMD5FileInfo.pBuffer = new CNCBuffer(nWidth, nHeight);
		ar.Read(sMD5FileInfo.pBuffer->m_pBuffer, nWidth * nHeight * sizeof(DWORD));
	}
	return ar;
}

SMD5FileInfo::SMD5FileInfo(CString strFilePath /*= _T("")*/,CTime tCreate/* = 0*/, CTime tModity/* = 0*/, __int64 nSize/* = 0*/)
{
	this->strFilePath = _T("");
	this->nFileType = -1;
	this->tCreate = tCreate;
	this->tModity = tModity;
	this->nSize = nSize;
	this->nSizeLoaded = 0;
	this->nWidth = 0;
	this->nHeight = 0;
	this->lDuration = 0;
	this->fFrameRate = 0.0f;
	this->nCodeRate = 0;
	this->pBuffer = NULL;
}

SMD5FileInfo::SMD5FileInfo(SMD5FileInfo const& sMD5FileInfo)
{
	pBuffer = NULL;

	*this = sMD5FileInfo;	
}

SMD5FileInfo::~SMD5FileInfo()
{
	if (pBuffer != NULL)
		DeletePtr(pBuffer);
}

SMD5FileInfo & SMD5FileInfo::operator = (const SMD5FileInfo& sMD5FileInfo)
{
	if (this == &sMD5FileInfo)
		return *this;

	this->strFilePath = sMD5FileInfo.strFilePath;
	this->nFileType = sMD5FileInfo.nFileType;
	this->tCreate = sMD5FileInfo.tCreate;
	this->tModity = sMD5FileInfo.tModity;
	this->nSize = sMD5FileInfo.nSize;
	this->nSizeLoaded = sMD5FileInfo.nSizeLoaded;
	this->nWidth = sMD5FileInfo.nWidth;
	this->nHeight = sMD5FileInfo.nHeight;
	this->lDuration = sMD5FileInfo.lDuration;
	this->fFrameRate = sMD5FileInfo.fFrameRate;
	this->nCodeRate = sMD5FileInfo.nCodeRate;
	
	if (pBuffer != NULL)
		DeletePtr(pBuffer);

	if (sMD5FileInfo.pBuffer != NULL && sMD5FileInfo.pBuffer->m_nWidth > 0 && sMD5FileInfo.pBuffer->m_nHeight > 0)
	{
		pBuffer = new CNCBuffer(sMD5FileInfo.pBuffer->m_nWidth, sMD5FileInfo.pBuffer->m_nHeight);
		G_CopyCNCBuffer(*pBuffer, *sMD5FileInfo.pBuffer);
	}

	return *this;
}

CTime SMD5FileInfo::StringToTime(CString strTime)
{
	COleVariant vtime(strTime);
	vtime.ChangeType(VT_DATE);
	COleDateTime oletime = vtime;
	SYSTEMTIME systime;
	VariantTimeToSystemTime(oletime, &systime);
	return CTime(systime);
}

CString	G_GetMD5FileName(CString strName, BOOL bLoadEnd /*= FALSE*/)
{
	CStringA strTempA = WToU8(strName);
	char *pMD5= MD5String(strTempA.GetBuffer());
	CString strMD5(pMD5, 32);
	delete[] pMD5;
	if (bLoadEnd)
		strMD5 += _T(".md");
	else
		strMD5 += _T(".md.back");
	return strMD5;
}

__int64	G_GetFileSize(CString strFilePath)
{
	HANDLE hFile = CreateFile(strFilePath, GENERIC_READ, PAGE_READONLY, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
	if (hFile == NULL)
		return 0;

	DWORD dwFileSizeHigh;
	__int64 nFileSize = GetFileSize(hFile, &dwFileSizeHigh);
	nFileSize |= (((__int64)dwFileSizeHigh) << 32);

	CloseHandle(hFile);
	hFile = NULL;

	return nFileSize;
}

BOOL G_IsFileInfoSame(SMD5FileInfo* pFileInfoSour, SMD5FileInfo* pFileInfoDes)
{
	if (pFileInfoSour == NULL || pFileInfoDes == NULL)
		return FALSE;

	if (pFileInfoSour->tCreate != pFileInfoDes->tCreate ||
		pFileInfoSour->tModity != pFileInfoDes->tModity ||
		pFileInfoSour->nSize != pFileInfoDes->nSize)
		return FALSE;
	return TRUE;
}

VOID G_GetFileInfo(CString strFilePath, SMD5FileInfo& sMD5FileInfo, int nWidth/* = 80*/, int nHeight/* = 45*/)
{
	if (strFilePath.IsEmpty())
		return;

	CFileStatus status;
	CFile::GetStatus(strFilePath, status);

	//构建SMD5FileInfo 信息
	sMD5FileInfo.strFilePath = strFilePath;
	sMD5FileInfo.tCreate = status.m_ctime;
	sMD5FileInfo.tModity = status.m_mtime;
	sMD5FileInfo.nSize = status.m_size;
	sMD5FileInfo.nFileType = GetClipTypeByExt(strFilePath);
	if (sMD5FileInfo.pBuffer == NULL)
		sMD5FileInfo.pBuffer = new CNCBuffer(nWidth, nHeight);
	G_LoadPreviewToBuffer(strFilePath, sMD5FileInfo.pBuffer, nWidth, nHeight);
	//TODO:下面这段需要改,获取文件类型的函数不对
	if (sMD5FileInfo.nFileType == TEXTURE_TYPE_PIC)
	{
		CNCBuffer buffer;
		buffer.CreateFromFile(strFilePath);
		if (buffer.m_pBuffer != NULL)
		{
			sMD5FileInfo.nWidth = buffer.GetWidth();
			sMD5FileInfo.nHeight = buffer.GetHeight();
		}
	}
	if (sMD5FileInfo.nFileType == TEXTURE_TYPE_VIDEOFILE)
	{
		IDPVAFileInfo pVAFileInfo;
		GetMediaFileVAInfo(strFilePath, pVAFileInfo, FILEINFO_VIDEO);
		sMD5FileInfo.nWidth = pVAFileInfo.sVideoInfo.nWidth;
		sMD5FileInfo.nHeight = pVAFileInfo.sVideoInfo.nHeight;
		sMD5FileInfo.lDuration = pVAFileInfo.sVideoInfo.nFrameCount;
		sMD5FileInfo.fFrameRate = pVAFileInfo.sVideoInfo.fFrameRate;
		sMD5FileInfo.nCodeRate = pVAFileInfo.sVideoInfo.nBitRate;
	}
}

VOID G_GetMd5FileInfo_Complete(CString strFilePath, SMD5FileInfo& sMD5FileInfo)
{
	if (strFilePath.IsEmpty())
		return;

	if (!PathFileExists(strFilePath))
		return;

	//读取文件内容
	CFile fileRead(strFilePath, CFile::modeRead);
	CArchive ar1(&fileRead, CArchive::load);
	ar1 >> sMD5FileInfo;
	ar1.Close();
	fileRead.Close();

	//根据当前的MD5文件路径,更新sMD5FileInfo中的文件路径
	CString strFloderPath = NCGetFilePath(strFilePath);
	CString strFileName = NCGetFileName(sMD5FileInfo.strFilePath);
	CString strFilePathNew = strFloderPath + strFileName;
	if (strFilePathNew != sMD5FileInfo.strFilePath)
	{
		sMD5FileInfo.strFilePath = strFilePathNew;
		//更新文件内容
		CFile fileWrite(strFilePath, CFile::modeWrite);
		CArchive ar2(&fileWrite, CArchive::store);
		ar2 << sMD5FileInfo;
		ar2.Close();
		fileWrite.Close();
	}
}

VOID G_GetMd5FileInfo_Loading(CString strFilePath, SMD5FileInfo& sMD5FileInfo)
{
	if (strFilePath.IsEmpty())
		return;

	if (!PathFileExists(strFilePath))
		return;

	CFile file(strFilePath, CFile::modeRead);
	CArchive ar(&file, CArchive::load);
	ar >> sMD5FileInfo.tCreate;
	ar >> sMD5FileInfo.tModity;
	ar >> sMD5FileInfo.nSize;
	ar >> sMD5FileInfo.nSizeLoaded;
}

VOID G_GetFileStatus(CString strFilePayh, SMD5FileInfo& sFileInfo)
{
	HANDLE hFile = CreateFile(strFilePayh, FILE_READ_EA, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
	if (hFile == NULL)
		return;

	DWORD dwFileSizeHigh;
	__int64 qwFileSize = GetFileSize(hFile, &dwFileSizeHigh);
	qwFileSize |= (((__int64)dwFileSizeHigh) << 32);
	sFileInfo.nSize = qwFileSize;
	FILETIME tCreate = { 0 };
	FILETIME tAccess = { 0 };
	FILETIME tModify = { 0 };
	GetFileTime(hFile, &tCreate, &tAccess, &tModify);

	sFileInfo.tCreate = tCreate;
	sFileInfo.tModity = tModify;
	//sFileInfo.tAccess = tAccess;

	CloseHandle(hFile);
}

SMD5FileInfo* G_GetMd5FileInfoByResPath(CString strFilePath)
{
	CString strFileName = NCGetFileName(strFilePath);
	CString strFolderPath = NCGetFilePath(strFilePath);
	CString strMD5FileName = G_GetMD5FileName(strFileName, TRUE);
	CString strMD5FilePath = strFolderPath + strMD5FileName;
	if (!PathFileExists(strMD5FilePath))
		return NULL;

	SMD5FileInfo* pFileInfo = new SMD5FileInfo;
	G_GetMd5FileInfo_Complete(strMD5FilePath, *pFileInfo);
	return pFileInfo;
}

文件复制类:
.h文件:

#pragma once
#include "Upload_DownloadInfo.h"

enum EErrorCode
{
	eErrorCode_None = -1,
	eErrorCode_CreateFile,				//创建文件对象失败
	eErrorCode_CreateFileMapping,		//创建文件映射内核对象失败
	eErrorCode_MapViewOfFile,			//映射文件映射失败
	eErrorCode_CreateMd5File,			//创建MD5码文件失败
};

typedef VOID	(CObject::*COPY_START_FUN)(CString strFileSour, DWORD dwSize, CObject* pFileCopy, CString strSign);
typedef VOID	(CObject::*COPY_GET_PROGRESS_FUN)(CString strFileSour, DWORD dwSize, DWORD dwFinished, CObject* pFileCopy, CString strSign);
typedef VOID	(CObject::*COPY_FINISHED_FUN)(CString strFileSour, CObject* pFileCopy, CString strSign);
typedef VOID	(CObject::*COPY_ERROR_FUN)(CString strFileSour, CString strFileDes, EErrorCode eErroeCode, CObject* pFileCopy, CString strSign);


class CFileCopyQuickly
{
	friend UINT threadFileCopy(LPVOID pParam);
public:
	CFileCopyQuickly();
	~CFileCopyQuickly();

	//设置需要复制的文件信息
	VOID				SetFileCopyInfo(ArFileCopyInfo& arFileCopyInfo);
	VOID				SetFileCopyInfo(ArPtrFileCopyInfo& arPtrFileCopyInfo);
	VOID				SetFileCopyInfo(SFileCopyInfo* pFileCopyInfo);
	//是否创建MD5码文件
	VOID				SetCreateMd5File(BOOL bCreate = TRUE);
	//设置特有标志
	VOID				SetSign(CString strSign);

	//代理和回调函数
	VOID				SetDelegation(CObject *pDelegation);
	VOID				SetCopyStartFun(COPY_START_FUN pCopyStartFun);
	VOID				SetGetCopyProgressFun(COPY_GET_PROGRESS_FUN pCopyProgressFun);
	VOID				SetCopyFinishedFun(COPY_FINISHED_FUN pCopyFinishedFun);
	VOID				SetCopyErrorFun(COPY_ERROR_FUN pCopyErrorFun);

	//回调函数使用接口
	VOID				CopyStart(CString strFileSour, DWORD dwSize);
	VOID				GetCopyProgress(CString strFileSour, DWORD dwSize, DWORD dwFinished);
	VOID				CopyFinished(CString strFileSour);
	VOID				CopyError(CString strFileSour, CString strFileDes, EErrorCode eErroeCode);

	//修改文件属性
	BOOL				ModifyDesFileAttributes(CString strFileSour, CString strFileDes);
	//创建.md文件
	BOOL				CreateMd5File_Complete(CString strFilePath, SMD5FileInfo* pMD5FileInfo);
	//创建.md.back文件
	BOOL				CreateMd5File_Loading(CString strFilePath, SMD5FileInfo* pMD5FileInfo);
	
	//线程控制
	VOID				Start();
	VOID				Pause();
	VOID				Resume();
	VOID				Stop();
	
public:

	ArFileCopyInfo		m_arFileCopyInfo;
	BOOL				m_bCreateMd5File;
	CString				m_strSign;

	CObject*			m_pDelegation;
	COPY_START_FUN		m_pCopyStartFun;
	COPY_GET_PROGRESS_FUN	m_pGetCopyProgressFun;
	COPY_FINISHED_FUN	m_pCopyFinishedFun;
	COPY_ERROR_FUN		m_pCopyErrorFun;

	CWinThread*				m_pThreadTime;
	HANDLE					m_hStopThread;
	HANDLE					m_hExitThread;
	HANDLE					m_hSuspendThread;//挂起线程
	CCriticalSection		m_lock;
};

typedef CArray<CFileCopyQuickly*, CFileCopyQuickly*> ArFileCopyQuickly;

.cpp文件:

#include "stdafx.h"
#include "FileCopyQuickly.h"
#include "md5.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif


CFileCopyQuickly::CFileCopyQuickly()
{
	m_arFileCopyInfo.SetSize(0);

	m_pDelegation = NULL;
	m_pCopyStartFun = NULL;
	m_pGetCopyProgressFun = NULL;
	m_pCopyFinishedFun = NULL;
	m_pCopyErrorFun = NULL;

	m_pThreadTime = NULL;
	m_hStopThread = CreateEvent(NULL, TRUE, FALSE, NULL);
	m_hExitThread = CreateEvent(NULL, TRUE, TRUE, NULL);
	m_hSuspendThread = CreateEvent(NULL, TRUE, FALSE, NULL);
	m_bCreateMd5File = TRUE;
	m_strSign = _T("");
}


CFileCopyQuickly::~CFileCopyQuickly()
{
	Stop();
}

VOID CFileCopyQuickly::SetDelegation(CObject *pDelegation)
{
	m_pDelegation = pDelegation;
}

VOID CFileCopyQuickly::SetCopyStartFun(COPY_START_FUN pCopyStartFun)
{
	m_pCopyStartFun = pCopyStartFun;
}

VOID CFileCopyQuickly::SetGetCopyProgressFun(COPY_GET_PROGRESS_FUN pCopyProgressFun)
{
	m_pGetCopyProgressFun = pCopyProgressFun;
}

VOID CFileCopyQuickly::SetCopyFinishedFun(COPY_FINISHED_FUN pCopyFinishedFun)
{
	m_pCopyFinishedFun = pCopyFinishedFun;
}

VOID CFileCopyQuickly::SetCopyErrorFun(COPY_ERROR_FUN pCopyErrorFun)
{
	m_pCopyErrorFun = pCopyErrorFun;
}

VOID CFileCopyQuickly::CopyStart(CString strFileSour, DWORD dwSize)
{
	if (m_pDelegation != NULL && m_pCopyStartFun != NULL)
		(m_pDelegation->*m_pCopyStartFun)(strFileSour, dwSize, (CObject*)this, m_strSign);
}

VOID CFileCopyQuickly::GetCopyProgress(CString strFileSour, DWORD dwSize, DWORD dwFinished)
{
	if (m_pDelegation != NULL && m_pGetCopyProgressFun != NULL)
		(m_pDelegation->*m_pGetCopyProgressFun)(strFileSour, dwSize, dwFinished, (CObject*)this, m_strSign);
}

VOID CFileCopyQuickly::CopyFinished(CString strFileSour)
{
	if (m_pDelegation != NULL && m_pCopyFinishedFun != NULL)
		(m_pDelegation->*m_pCopyFinishedFun)(strFileSour, (CObject*)this, m_strSign);
}

VOID CFileCopyQuickly::CopyError(CString strFileSour, CString strFileDes, EErrorCode eErroeCode)
{
	if (m_pDelegation != NULL && m_pCopyErrorFun != NULL)
		(m_pDelegation->*m_pCopyErrorFun)(strFileSour, strFileDes, eErroeCode, (CObject*)this, m_strSign);
}

BOOL CFileCopyQuickly::ModifyDesFileAttributes(CString strFileSour, CString strFileDes)
{
	if (strFileSour.IsEmpty() || strFileDes.IsEmpty())
		return FALSE;
	
	//修改目标文件的属性与源文件一致
	CFileStatus statusSour;
	CFileStatus statusDes;
	CFile::GetStatus(strFileSour, statusSour);
	CFile::GetStatus(strFileDes, statusDes);

	ASSERT(statusSour.m_size == statusDes.m_size);
	if (statusSour.m_size != statusDes.m_size)
		return FALSE;

	statusDes.m_ctime = statusSour.m_ctime;
	statusDes.m_mtime = statusSour.m_mtime;
	statusDes.m_attribute = statusSour.m_attribute;
	CFile::SetStatus(strFileDes, statusDes);
	
	return TRUE;
}

BOOL CFileCopyQuickly::CreateMd5File_Complete(CString strFilePath, SMD5FileInfo* pMD5FileInfo)
{
	if (strFilePath.IsEmpty() || pMD5FileInfo == NULL)
		return FALSE;

	//创建文件并写入
	CFile file(strFilePath, CFile::modeCreate | CFile::modeWrite);
	CArchive ar(&file, CArchive::store); 
	ar << *pMD5FileInfo;
	ar.Close();
	file.Close();
	return TRUE;
}

BOOL CFileCopyQuickly::CreateMd5File_Loading(CString strFilePath, SMD5FileInfo* pMD5FileInfo)
{
	if (strFilePath.IsEmpty() || pMD5FileInfo == NULL)
		return FALSE;
	
	//创建文件并写入
	CFile file(strFilePath, CFile::modeCreate | CFile::modeWrite);
	CArchive ar(&file, CArchive::store);
	//如果不是Load完之后生成的MD5文件,则不需要串出去那么多的数据,影响Load速度
	ar << pMD5FileInfo->tCreate;
	ar << pMD5FileInfo->tModity;
	ar << pMD5FileInfo->nSize;
	ar << pMD5FileInfo->nSizeLoaded;
	ar.Close();
	file.Close();
	return TRUE;
}

VOID CFileCopyQuickly::SetFileCopyInfo(ArFileCopyInfo& arFileCopyInfo)
{
	//Stop();
	m_arFileCopyInfo.RemoveAll();
	m_arFileCopyInfo.Copy(arFileCopyInfo);
}

VOID CFileCopyQuickly::SetFileCopyInfo(ArPtrFileCopyInfo& arPtrFileCopyInfo)
{
	//Stop();
	m_arFileCopyInfo.RemoveAll();
	for (int i = 0; i < (int)arPtrFileCopyInfo.GetCount(); i++)
	{
		SFileCopyInfo* pCopyInfo = arPtrFileCopyInfo[i];
		if (pCopyInfo == NULL)
			continue;

		SFileCopyInfo sCopyInfo(pCopyInfo);
		m_arFileCopyInfo.Add(sCopyInfo);
	}
}

VOID CFileCopyQuickly::SetFileCopyInfo(SFileCopyInfo* pFileCopyInfo)
{
	//Stop();
	m_arFileCopyInfo.RemoveAll();
	SFileCopyInfo sCopyInfo(*pFileCopyInfo);
	m_arFileCopyInfo.Add(sCopyInfo);
}

VOID CFileCopyQuickly::SetCreateMd5File(BOOL bCreate /*= TRUE*/)
{
	m_bCreateMd5File = bCreate;
}

VOID CFileCopyQuickly::SetSign(CString strSign)
{
	m_strSign = strSign;
}

VOID CFileCopyQuickly::Start()
{
	if (m_pThreadTime == NULL)
	{
		ResetEvent(m_hStopThread);
		m_pThreadTime = AfxBeginThread(threadFileCopy, this, THREAD_PRIORITY_NORMAL, 0, 0);
	}
	SetEvent(m_hSuspendThread);
}

VOID CFileCopyQuickly::Pause()
{
	if (m_pThreadTime == NULL)
		return;
	ResetEvent(m_hSuspendThread);
}

VOID CFileCopyQuickly::Resume()
{
	if (m_pThreadTime == NULL)
		return;
	SetEvent(m_hSuspendThread);
}

VOID CFileCopyQuickly::Stop()
{
	if (m_pThreadTime)
	{
		SetEvent(m_hStopThread);
		SetEvent(m_hSuspendThread);
		WaitForSingleObject(m_hExitThread, INFINITE);
		m_pThreadTime = NULL;
	}
}

UINT threadFileCopy(LPVOID pParam)
{
	CFileCopyQuickly* pFileCopy = (CFileCopyQuickly*)pParam;
	if (pFileCopy == NULL)
		return 0;

	//系统粒度的大小
	SYSTEM_INFO sys;
	GetSystemInfo(&sys);
	DWORD dwGran = sys.dwAllocationGranularity;     
	
	ResetEvent(pFileCopy->m_hExitThread);
	while (1)
	{
		//只有设置了m_hSuspendThread,线程才生效
		WaitForSingleObject(pFileCopy->m_hSuspendThread, INFINITE);
		if (WaitForSingleObject(pFileCopy->m_hStopThread, 1) == WAIT_OBJECT_0)
			break;
		
		//复制出来一份数据,进行下面的文件复制功能
		ArFileCopyInfo	arFileCopyInfo;
		arFileCopyInfo.Copy(pFileCopy->m_arFileCopyInfo);

		for (int i = 0; i < (int)arFileCopyInfo.GetCount(); i++)
		{
			WaitForSingleObject(pFileCopy->m_hSuspendThread, INFINITE);
			if (WaitForSingleObject(pFileCopy->m_hStopThread, 0) == WAIT_OBJECT_0)
			{
				SetEvent(pFileCopy->m_hExitThread);
				return 1;
			}
			CString strFileSour = arFileCopyInfo[i].strFileSour;
			CString strFileDes = arFileCopyInfo[i].strFileDes;
			//文件名称
			CString strFileName = NCGetFileName(strFileSour);
			//文件夹
			CString strFilePath = NCGetFilePath(strFileDes);
			//如果路径不存在,创建路径
			if (!PathIsDirectory(strFilePath))
			{
				if (!NCCreateDirectory(strFilePath))
					continue;
			}

			//打开文件对象
			HANDLE hFileSour = CreateFile(strFileSour, GENERIC_READ | GENERIC_WRITE, PAGE_READONLY | FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
			HANDLE hFileDes = CreateFile(strFileDes, GENERIC_READ | GENERIC_WRITE, PAGE_READWRITE, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
			if (hFileSour == INVALID_HANDLE_VALUE || hFileDes == INVALID_HANDLE_VALUE)
			{
				if (hFileSour != INVALID_HANDLE_VALUE)
					CloseHandle(hFileSour);
				if (hFileDes != INVALID_HANDLE_VALUE)
					CloseHandle(hFileDes);
				pFileCopy->CopyError(strFileSour, strFileDes, eErrorCode_CreateFile);
				continue;
			}

			//文件大小
			__int64	nFileSize = 0;
			//剩余大小
			__int64 nFileSizeLast = 0;
			//已经下载大小,只在初始化的时候用
			__int64	nLoadedSize = 0;

			
			//下载完的MD5码文件名称
			CString strMD5_Complete = G_GetMD5FileName(NCGetFileName(strFileDes), TRUE);
			//下载中的MD5码文件名称(中间文件)
			CString strMD5_Loading = G_GetMD5FileName(NCGetFileName(strFileDes));
			//两个md5文件绝对路径
			CString strMd5Path_Complete = strFilePath + strMD5_Complete;
			CString strMd5Path_Loading = strFilePath + strMD5_Loading;

			//这里需要根据源文件建立MD5文件信息
			SMD5FileInfo sMD5FileInfo;
			G_GetFileInfo(strFileSour, sMD5FileInfo);

			//查看.md文件是否存在
			if (PathFileExists(strMd5Path_Complete))
			{
				SMD5FileInfo sMD5FileInfo_Complete;
				G_GetMd5FileInfo_Complete(strMd5Path_Complete, sMD5FileInfo_Complete);
				//文件已经load完成了,跳过
				if (G_IsFileInfoSame(&sMD5FileInfo, &sMD5FileInfo_Complete))
				{
					CloseHandle(hFileSour);
					CloseHandle(hFileDes);
					continue;
				}
				//.md文件存在,信息不一样,说明现在这个目标文件没用了
				else
				{
					DeleteFile(strMd5Path_Complete);
					if (PathFileExists(strFileDes))
					{
						//hFileDes必须重新构建,因为原来的文件已经删除了,原来的hFileDes也无用了,用原来的hFileDes
						//继续执行下面的代码,会文件拷贝失败
						CloseHandle(hFileDes);
						DeleteFile(strFileDes);
						hFileDes = CreateFile(strFileDes, GENERIC_READ | GENERIC_WRITE, PAGE_READWRITE, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
						if (hFileDes == NULL)
						{
							CloseHandle(hFileSour);
							pFileCopy->CopyError(strFileSour, strFileDes, eErrorCode_CreateFile);
							continue;
						}
					}
				}
			}

			//得到源文件大小
			nFileSize = sMD5FileInfo.nSize;
			nFileSizeLast = nFileSize;
			//创建一个文件映射内核对象
			HANDLE hFileMappingSour = CreateFileMapping(hFileSour, NULL, PAGE_READWRITE, 0, (DWORD)nFileSize, NULL);
			HANDLE hFileMappingDes = CreateFileMapping(hFileDes, NULL, PAGE_READWRITE, 0, (DWORD)nFileSize, NULL);
			if (hFileMappingSour == NULL || hFileMappingDes == NULL)
			{
				if (hFileMappingSour != INVALID_HANDLE_VALUE)
					CloseHandle(hFileMappingSour);
				if (hFileMappingDes != INVALID_HANDLE_VALUE)
					CloseHandle(hFileMappingDes);
				CloseHandle(hFileSour);
				CloseHandle(hFileDes);
				pFileCopy->CopyError(strFileSour, strFileDes, eErrorCode_CreateFileMapping);
				continue;
			}
			CloseHandle(hFileSour);
			CloseHandle(hFileDes);
		
			//判断是否存在.md.back文件
			if (PathFileExists(strMd5Path_Loading))
			{
				SMD5FileInfo sMD5FileInfo_Loading;
				G_GetMd5FileInfo_Loading(strMd5Path_Loading, sMD5FileInfo_Loading);
				//如果信息一样,则是断点续传
				if (G_IsFileInfoSame(&sMD5FileInfo, &sMD5FileInfo_Loading))
				{
					nFileSizeLast = nFileSize - sMD5FileInfo_Loading.nSizeLoaded;
					nLoadedSize = sMD5FileInfo_Loading.nSizeLoaded;
				}
				else
				{
					DeleteFile(strMd5Path_Loading);
					if (PathFileExists(strFileDes))
					{
						//hFileDes必须重新构建,因为原来的文件已经删除了,原来的hFileDes也无用了,用原来的hFileDes
						//继续执行下面的代码,会文件拷贝失败
						CloseHandle(hFileDes);
						DeleteFile(strFileDes);
						hFileDes = CreateFile(strFileDes, GENERIC_READ | GENERIC_WRITE, PAGE_READWRITE, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
						if (hFileDes == NULL)
						{
							CloseHandle(hFileSour);
							pFileCopy->CopyError(strFileSour, strFileDes, eErrorCode_CreateFile);
							continue;
						}
					}
				}
			}
			
			//开始复制
			pFileCopy->CopyStart(strFileSour, (DWORD)nFileSize);

			// 偏移地址 
			__int64 qwFileOffset = nLoadedSize;
			// 块大小
			DWORD dwBlockBytes = 100 * dwGran;
			if (nFileSizeLast < 100 * dwGran)
				dwBlockBytes = (DWORD)nFileSizeLast;

			BOOL bError = FALSE;
			while (nFileSizeLast > 0)
			{
				WaitForSingleObject(pFileCopy->m_hSuspendThread, INFINITE);
				if (WaitForSingleObject(pFileCopy->m_hStopThread, 0) == WAIT_OBJECT_0)
				{
					CloseHandle(hFileMappingSour);
					CloseHandle(hFileMappingDes);

					//创建和更新下载中间文件信息(.md.back文件)
					SMD5FileInfo sMD5FileInfo_Loading;
					sMD5FileInfo_Loading.tCreate = sMD5FileInfo.tCreate;
					sMD5FileInfo_Loading.tModity = sMD5FileInfo.tModity;
					sMD5FileInfo_Loading.nSize = sMD5FileInfo.nSize;
					sMD5FileInfo_Loading.nSizeLoaded = qwFileOffset;
					pFileCopy->CreateMd5File_Loading(strMd5Path_Loading, &sMD5FileInfo_Loading);

					SetEvent(pFileCopy->m_hExitThread);
					return 1;
				}

				//MapViewOfFile负责把文件数据映射到进程的地址空间
				LPBYTE lpbMapAddressSour = (LPBYTE)MapViewOfFile(hFileMappingSour, FILE_MAP_ALL_ACCESS, (DWORD)(qwFileOffset >> 32), (DWORD)(qwFileOffset & 0xFFFFFFFF), dwBlockBytes);
				LPBYTE lpbMapAddressDes = (LPBYTE)MapViewOfFile(hFileMappingDes, FILE_MAP_ALL_ACCESS, (DWORD)(qwFileOffset >> 32), (DWORD)(qwFileOffset & 0xFFFFFFFF), dwBlockBytes);
				if (lpbMapAddressSour == NULL || lpbMapAddressDes == NULL)
				{
					bError = TRUE;
					break;
				}

				//数据拷贝
				memcpy(lpbMapAddressDes, lpbMapAddressSour, dwBlockBytes);

				// 撤消文件映像
				UnmapViewOfFile(lpbMapAddressSour);
				UnmapViewOfFile(lpbMapAddressDes);

				// 修正参数
				qwFileOffset += dwBlockBytes;
				nFileSizeLast -= dwBlockBytes;
				if (nFileSizeLast < dwBlockBytes)
					dwBlockBytes = (DWORD)nFileSizeLast;

				//文件复制进度
				pFileCopy->GetCopyProgress(strFileSour, (DWORD)nFileSize, (DWORD)qwFileOffset);
			}
			CloseHandle(hFileMappingSour);
			CloseHandle(hFileMappingDes);
			DeleteFile(strMd5Path_Loading);
			if (bError)
			{
				pFileCopy->CopyError(strFileSour, strFileDes, eErrorCode_MapViewOfFile);
				continue;
			}
			
			//修改文件属性
			pFileCopy->ModifyDesFileAttributes(strFileSour, strFileDes);
			//创建md5文件
			if (pFileCopy->m_bCreateMd5File)
			{
				if (!pFileCopy->CreateMd5File_Complete(strMd5Path_Complete, &sMD5FileInfo))
				{
					pFileCopy->CopyError(strFileSour, strFileDes, eErrorCode_CreateMd5File);
					continue;
				}
			}

			//最后一个文件完成,挂起线程
			if (i == (int)arFileCopyInfo.GetCount() - 1)
				ResetEvent(pFileCopy->m_hSuspendThread);

			//该文件复制完成
			pFileCopy->CopyFinished(strFileSour);
		}
	}
	SetEvent(pFileCopy->m_hExitThread);
	return 1;
}

窗口界面自己去实现了

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值