在服务中、一般程序中利用 Inet 相关函数下载数据[原创]
虽然可以使用 URLDownloadFileToXXX() 这个 API,但是,它在使用了代理的时候会遇到麻烦。
这点,Windows 自动更新发生过这样的问题:如果使用了 IE 代理,如果下载代码位于系统帐号
下,代理设置可能会失效。当然,也可以为系统帐号手动设置代理(其实就是 IE 的代理的设置
方法),不过,程序会受到很多的限制。
所以,可以考虑使用下属两个函数进行使用 - 服务程序亦可。
// Download a file from the URL.
bool CHttpDownload::UrlDownloadToFile(TCHAR *ptszURL, TCHAR *ptszFilePath)
{
HINTERNET hNet;
HINTERNET hFile;
std::string sProxyServer;
DWORD dwStatusCode;
TCHAR dwStatusCode1[32] = {0};
DWORD dwSize1 = sizeof(dwStatusCode1), dwSize = sizeof(DWORD);
int nfilesize; // file size, 2GB limited. ;)
m_sUrl = ptszURL;
//OutputDebugString("\nCHttpDownload::UrlDownloadToFile() ++");
//
if(m_ConnectionType == UseProxy)
{
//OutputDebugString("\n ==> Useproxy");
hNet = InternetOpen(tszAgent, INTERNET_OPEN_TYPE_PROXY, m_sProxy.c_str(), NULL, 0);
}
else if(m_ConnectionType == DirectToInternet)
{
//OutputDebugString("\n ==> DirectToInternet");
hNet = InternetOpen(tszAgent, INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
}
else if(m_ConnectionType == UsePreConfig)
{
//OutputDebugString("\n ==> UsePreConfig");
hNet = InternetOpen(tszAgent, INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
}
if(hNet == NULL)
{
//OutputDebugString("\nCHttpDownload::UrlDownloadToFile() --.1");
return false;
}
hFile = InternetOpenUrl(hNet, m_sUrl.c_str(), NULL, 0, 0, 0);
if(hFile == NULL)
{
InternetCloseHandle(hNet) ;
//OutputDebugString(m_sUrl.c_str());
//OutputDebugString(ptszURL);
//OutputDebugString("\nCHttpDownload::UrlDownloadToFile() --.2");
return false;
}
BOOL bRet = HttpQueryInfo(hFile, HTTP_QUERY_STATUS_CODE|HTTP_QUERY_FLAG_NUMBER,&dwStatusCode,&dwSize,NULL);
if(200 != dwStatusCode) // if URI is not exist, give up.
{
InternetCloseHandle(hNet) ;
InternetCloseHandle(hFile) ;
//OutputDebugString("\nCHttpDownload::UrlDownloadToFile() --.3");
return false;
}
if(HttpQueryInfo(hFile,HTTP_QUERY_CONTENT_LENGTH, &dwStatusCode1,&dwSize1,NULL))
{
nfilesize = atoi(dwStatusCode1); // file size.
}
HANDLE hDownFile = CreateFile(ptszFilePath,
GENERIC_READ|GENERIC_WRITE,
FILE_SHARE_READ,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL);
if(INVALID_HANDLE_VALUE == hDownFile)
{
InternetCloseHandle(hNet) ;
InternetCloseHandle(hFile) ;
//OutputDebugString("\nCHttpDownload::UrlDownloadToFile() --.4");
return false;
}
// O.K. save file
DWORD dwWrite, dwBytesRead = 0;
char bufFile[MAX_BUFFER_SIZE] = {0};
DWORD dwSurplus = nfilesize % sizeof(bufFile);
while(true)
{
// Read File Data From Net.
BOOL bRead = InternetReadFile(hFile, bufFile, sizeof(bufFile), &dwBytesRead);
if(dwBytesRead == 0) // End of file.
break;
// Write file data.
WriteFile(hDownFile, bufFile, dwBytesRead, &dwWrite,NULL);
}
InternetCloseHandle(hFile) ;
InternetCloseHandle(hNet) ;
CloseHandle(hDownFile) ;
//OutputDebugString("\nCHttpDownload::UrlDownloadToFile() --.");
return true;
}
// Download URL contents to memory buffer.
// if pBuf == NULL, *pdwBufSize will contain the real size of remote size;
// *pdwBufSize alwayls contains the size of remote size.
bool CHttpDownload::UrlDownloadToBuffer(TCHAR *ptszURL, LPVOID pBuf, DWORD *pdwBufSize)
{
HINTERNET hNet;
HINTERNET hFile;
std::string sProxyServer;
DWORD dwStatusCode;
TCHAR dwStatusCode1[32] = {0};
DWORD dwSize1 = sizeof(dwStatusCode1), dwSize = sizeof(DWORD);
int nfilesize; // file size, 2GB limited. ;)
m_sUrl = ptszURL;
//OutputDebugString("\nCHttpDownload::UrlDownloadToFile() ++");
//
if(m_ConnectionType == UseProxy)
hNet = InternetOpen(tszAgent, INTERNET_OPEN_TYPE_PROXY, m_sProxy.c_str(), NULL, 0);
else if(m_ConnectionType == DirectToInternet)
hNet = InternetOpen(tszAgent, INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
else if(m_ConnectionType == UsePreConfig)
hNet = InternetOpen(tszAgent, INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
if(hNet == NULL)
{
//OutputDebugString("\nCHttpDownload::UrlDownloadToFile() --.1");
return false;
}
hFile = InternetOpenUrl(hNet, m_sUrl.c_str(), NULL, 0, 0, 0);
if(hFile == NULL)
{
InternetCloseHandle(hNet) ;
//OutputDebugString("\nCHttpDownload::UrlDownloadToFile() --.2");
return false;
}
BOOL bRet = HttpQueryInfo(hFile, HTTP_QUERY_STATUS_CODE|HTTP_QUERY_FLAG_NUMBER,&dwStatusCode,&dwSize,NULL);
if(200 != dwStatusCode) // if URI is not exist, give up.
{
InternetCloseHandle(hNet) ;
InternetCloseHandle(hFile) ;
//OutputDebugString("\nCHttpDownload::UrlDownloadToFile() --.3");
return false;
}
if(HttpQueryInfo(hFile, HTTP_QUERY_CONTENT_LENGTH, &dwStatusCode1, &dwSize1, NULL))
{
nfilesize = atoi(dwStatusCode1); // file size.
}
char szBuffer[MAX_BUFFER_SIZE+1] = {0};
if(pBuf != NULL) // We only copy the 1st MAX_BUFFER_SIZE data to user buffer!!!
{
unsigned long nSize = 0;
BOOL bRet = InternetReadFile(hFile, szBuffer, MAX_BUFFER_SIZE, &nSize);
szBuffer[nSize] = '\0';
// dump buffer.
DWORD dwtSize = (*pdwBufSize > nSize)? nSize: *pdwBufSize;
memcpy(pBuf, szBuffer, dwtSize);
}
*pdwBufSize = nfilesize;
InternetCloseHandle(hFile) ;
InternetCloseHandle(hNet) ;
return true;
}
注意,
用HTTP_QUERY_CONTENT_LENGTH只是返回本次请求得到数据的长度,如果要得到整个文件的大小,
用HTTP_QUERY_CONTENT_RANGE,然后解析得到的字符串,就可以了。
HTTP_STATUS_OK = 200
***************************************************************************************
用CHttpFile实现简单的GET/POST数据
一、GET 数据,下载网页,文件等,用于可下载的文件,不能用于服务端运行的程序,比如.aspx文件等,否则会返回500错误。
CString strSentence, strWriteName="1.htm";
CString strFileName="http://localhost/InDesign/" + strWriteName;
CInternetSession sess;
CHttpFile* fileGet;
try
{
fileGet=(CHttpFile*)sess.OpenURL(strFileName);
}
catch(CException* e)
{
fileGet = 0;
throw;
}
if(fileGet)
{
DWORD dwStatus;
DWORD dwBuffLen = sizeof(dwStatus);
BOOL bSuccess = fileGet->QueryInfo(HTTP_QUERY_STATUS_CODE|HTTP_QUERY_FLAG_NUMBER, &dwStatus, &dwBuffLen);
if( bSuccess && dwStatus>= 200 && dwStatus<300 )
{
CStdioFile fileWrite;
if(fileWrite.Open(strWriteName, CFile::modeWrite|CFile::modeCreate))
{
while(fileGet->ReadString(strSentence))
{
fileWrite.WriteString(strSentence+"\n");
}
fileWrite.Close();
AfxMessageBox("下载完毕");
}
else
{
AfxMessageBox("本地文件"+strWriteName+"打开出错.");
}
}
else
{
strSentence.Format("打开网页文件出错,错误码:%d", dwStatus);
AfxMessageBox(strSentence);
}
fileGet->Close();
delete fileGet;
}
else
AfxMessageBox("不能找到网页文件!");
sess.Close();
二、POST 数据,比如用于提交注册信息等
CString strHttpName="http://localhost/TestReg/RegForm.aspx"; // 需要提交数据的页面
CString strFormData = "username=abc&password=123"; // 需要提交的数据
CInternetSession sess;
CHttpFile* fileGet;
CString strHeaders = _T("Content-Type: application/x-www-form-urlencoded"); // 请求头
try
{
fileGet=(CHttpFile*)sess.OpenURL(strHttpName);//打开文件
}
catch(CException* e)
{
fileGet = 0;
throw;
}
CString strSentence, strGetSentence = "";
if(fileGet)
{
DWORD dwStatus;
DWORD dwBuffLen = sizeof(dwStatus);
BOOL bSuccess = fileGet->QueryInfo(HTTP_QUERY_STATUS_CODE|HTTP_QUERY_FLAG_NUMBER, &dwStatus, &dwBuffLen);
if( bSuccess && dwStatus>= 200 &&dwStatus<300 )
{
BOOL result = fileGet->SendRequest(strHeaders, (LPVOID)(LPCTSTR)strFormData, strFormData.GetLength());
while(fileGet->ReadString(strSentence)) // 读取提交数据后的返回结果
{
strGetSentence = strGetSentence + strSentence + char(13) + char(10);
}
AfxMessageBox(strGetSentence); // 显示返回网页内容
}
else
{
strSentence.Format("POST出错,错误码:%d", dwStatus);
AfxMessageBox(strSentence);
}
fileGet->Close();
delete fileGet;
}
else
AfxMessageBox("不能找到网页文件!");
sess.Close();
当然也可以用直接用Api函数URLDownloadToFile()来下载一个文件.
评论