// Mydownload.cpp : 定义 DLL 应用程序的入口点。
#include "MyDownload.h"
#include <sys/stat.h> // 状态显示头文件.
#include "ChineseCode.h"
#include <iostream>
using namespace std;
#ifdef _MANAGED
#pragma managed(pop)
#endif
int CHttpGet::m_nCount;
DWORD CHttpGet::m_nFileLength = 0;
//unsigned long CHttpGet::m_downloaded = 0;
unsigned long rdownloaded = 0;
void ParseURL(CString URL,CString &host,CString &path,CString &filename)
{
URL.TrimLeft();
URL.TrimRight();
CString str=URL;
CString strFind=_T("http://");
int n=str.Find(strFind);
if(n!=-1){
str.Delete(0, n+strFind.GetLength());
}
n=str.Find('/');
host = str.Left(n);
n=URL.ReverseFind('/');
path = URL.Left(n+1);
filename = URL.Right(URL.GetLength()-n-1);
}
// 这是导出函数的一个示例。
bool fnMyDownload(CString strUrl,
CString strWriteFileName,
unsigned long *& downloaded,
unsigned long & totalSize,
CString strProxy,
int nProxyPort,
int nThread
)
{
CHttpGet b;
CString strHostAddr;
CString strHttpAddr;
CString strHttpFilename;
//用于跟踪实时下载数据
downloaded = &rdownloaded;
ParseURL(strUrl,strHostAddr,strHttpAddr,strHttpFilename);
strWriteFileName += strHttpFilename; //本地文件名还是保留GB2312
//http默认是UTF8编码,所以把中文编码为UTF8
ChineseCode chineseCode;
string remoteFileName; //文件名
chineseCode.GB2312ToUTF_8(remoteFileName, (char*)strHttpFilename.GetBuffer(strHttpFilename.GetLength()), strHttpFilename.GetLength());
strHttpFilename = remoteFileName.c_str();
string remoteFilePath; //服务器的文件路径 "http://www.123.com/123/"
chineseCode.GB2312ToUTF_8(remoteFilePath, (char*)strHttpAddr.GetBuffer(strHttpAddr.GetLength()), strHttpAddr.GetLength());
strHttpAddr = remoteFilePath.c_str();
//cout<<strHttpAddr.GetBuffer(strHttpAddr.GetLength())<<endl;
if(strProxy != ""){
if(!b.HttpDownLoadProxy(strProxy,nProxyPort,strHostAddr,strHttpAddr,strHttpFilename,strWriteFileName,nThread,totalSize))
return false;
}
else{
if(!b.HttpDownLoadNonProxy(strHostAddr,strHttpAddr,strHttpFilename,strWriteFileName,nThread,totalSize))
return false;
}
return true;
}
//---------------------------------------------------------------------------
CHttpGet::CHttpGet()
{
m_nFileLength=0;
}
//---------------------------------------------------------------------------
CHttpGet::~CHttpGet()
{
}
//---------------------------------------------------------------------------
BOOL CHttpGet::HttpDownLoadProxy(
CString strProxyAddr,
int nProxyPort,
CString strHostAddr,
CString strHttpAddr,
CString strHttpFilename,
CString strWriteFileName,
int nSectNum,
DWORD &totalSize
)
{
SOCKET hSocket;
hSocket=ConnectHttpProxy(strProxyAddr,nProxyPort);
if(hSocket == INVALID_SOCKET) return 1;
// 发送文件头,计算文件大小.
SendHttpHeader(hSocket,strHostAddr,strHttpAddr,strHttpFilename,0);
closesocket(hSocket);
totalSize = CHttpGet::m_nFileLength;
if(!HttpDownLoad(strProxyAddr,nProxyPort,strHostAddr,80,strHttpAddr,strHttpFilename,strWriteFileName,nSectNum,true))
return FALSE;
return TRUE;
}
//---------------------------------------------------------------------------
BOOL CHttpGet::HttpDownLoadNonProxy(
CString strHostAddr,
CString strHttpAddr,
CString strHttpFilename,
CString strWriteFileName,
int nSectNum,
DWORD &totalSize)
{
int nHostPort=80;
SOCKET hSocket;
hSocket=ConnectHttpNonProxy(strHostAddr,nHostPort);
if(hSocket == INVALID_SOCKET) return 1;
// 发送文件头,计算文件大小.
SendHttpHeader(hSocket,strHostAddr,strHttpAddr,strHttpFilename,0);
closesocket(hSocket);
totalSize = CHttpGet::m_nFileLength;
if(!HttpDownLoad(TEXT(""),80,strHostAddr,nHostPort,strHttpAddr,strHttpFilename,strWriteFileName,nSectNum,false))
return FALSE;
return TRUE;
}
//---------------------------------------------------------------------------
BOOL CHttpGet::HttpDownLoad(
CString strProxyAddr,
int nProxyPort,
CString strHostAddr,
int nHostPort,
CString strHttpAddr,
CString strHttpFilename,
CString strWriteFileName,
int nSectNum,
BOOL bProxy)
{
ASSERT(nSectNum>0 && nSectNum<=50);
m_nCount=0; // 把计数器清零.
sectinfo=new CHttpSect[nSectNum]; // 给信息结构申请内存.
DWORD nSize= m_nFileLength/nSectNum; // 计算分割段的大小.
int i;
// 创建线程.不能超过50个。
CWinThread* pthread[50];
for(i=0;i<nSectNum;i++)
{
sectinfo[i].szProxyAddr=strProxyAddr; // 代理服务器地址.
sectinfo[i].nProxyPort =nProxyPort; // Host地址.
sectinfo[i].szHostAddr =strHostAddr; // Http文件地址.
sectinfo[i].nHostPort =nHostPort; // Http文件名.
sectinfo[i].szHttpAddr =strHttpAddr; // 代理服务端口号.
sectinfo[i].szHttpFilename=strHttpFilename;// Host端口号.
sectinfo[i].bProxyMode=bProxy; // 下载模态.
// 计算临时文件名.
CString strTempFileName;
strTempFileName.Format("%s_%d",strWriteFileName, i);
sectinfo[i].szDesFilename=strTempFileName; // 下载后的文件名.
if(i<nSectNum-1){
sectinfo[i].nStart=i*nSize; // 分割的起始位置.
sectinfo[i].nEnd=(i+1)*nSize; // 分割的终止位置.
}
else{
sectinfo[i].nStart=i*nSize; // 分割的起始位置.
//sectinfo[i].nStart=1744896; // 分割的起始位置.
sectinfo[i].nEnd=m_nFileLength; // 分割的终止位置.
}
// AfxBeginThread(ThreadDownLoad,§info[i],THREAD_PRIORITY_HIGHEST);
pthread[i] = AfxBeginThread(ThreadDownLoad,§info[i]);
}
HANDLE hThread[50];
for(int ii = 0 ; ii < nSectNum ; ii++)
hThread[ii] = pthread[ii]->m_hThread;
// 等待所有线程结束.
WaitForMultipleObjects(nSectNum,hThread,TRUE,INFINITE);
//有某个文件块未下载完,返回错误,应由最上层调用者重新下载。
if(m_nCount != nSectNum)
return FALSE;
FILE *fpwrite;
// 打开写文件.
if((fpwrite=fopen(strWriteFileName,"wb"))==NULL){
return FALSE;
}
for(i=0;i<nSectNum;i++){
FileCombine(§info[i],fpwrite);
}
fclose(fpwrite);
delete[] sectinfo;
return TRUE;
}
//---------------------------------------------------------------------------
BOOL CHttpGet::FileCombine(CHttpSect *pInfo, FILE *fpwrite)
{
FILE *fpread;
// 打开文件.
if((fpread=fopen(pInfo->szDesFilename,"rb"))==NULL)
return FALSE;
DWORD nPos=pInfo->nStart;
// 设置文件写指针起始位置.
fseek(fpwrite,nPos,SEEK_SET);
int c;
// 把文件数据写入到子文件.
while((c=fgetc(fpread))!=EOF)
{
fputc(c,fpwrite);
nPos++;
if(nPos==pInfo->nEnd) break;
}
fclose(fpread);
DeleteFile(pInfo->szDesFilename);
return TRUE;
}
//---------------------------------------------------------------------------
UINT CHttpGet::ThreadDownLoad(void* pParam)
{
CHttpSect *pInfo=(CHttpSect*)pParam;
SOCKET hSocket;
if(pInfo->bProxyMode){
hSocket=ConnectHttpProxy(pInfo->szProxyAddr,pInfo->nProxyPort);
}
else{
hSocket=ConnectHttpNonProxy(pInfo->szHostAddr,pInfo->nHostPort);
}
if(hSocket == INVALID_SOCKET) return 1;
// 计算临时文件大小,为了断点续传
DWORD nFileSize=myfile.GetFileSizeByName(pInfo->szDesFilename);
DWORD nSectSize=(pInfo->nEnd)-(pInfo->nStart);
// 此段已下载完毕.
if(nFileSize==nSectSize){
//mj
printf("文件下载成功!下载结束!\n"); //这里可以设置写信息
//mj
TRACE("文件已下载完毕!\n");
CHttpGet::m_nCount++; // 计数.
return 0;
}
FILE *fpwrite=myfile.GetFilePointer(pInfo->szDesFilename);
if(!fpwrite) return 1;
// 设置下载范围.
SendHttpHeader(hSocket,pInfo->szHostAddr,pInfo->szHttpAddr,
pInfo->szHttpFilename,pInfo->nSta
- 1
- 2
- 3
- 4
前往页