基本数据类:(复制文件过程中用到的基本数据类)
.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;
}
窗口界面自己去实现了