我想写一个多线程下载的命令行程序。但是在使用wininet.lib提供的api函数时遇到了问题
源代码如下
#include "stdio.h"
#include "windows.h"
#include "wininet.h"void usage();
LPTSTR GetFileName(LPCTSTR lpszFilePath);
void ShowError(LPCSTR lpszFuntionName);int main(int argc,char *argv[])
{
HINTERNET hSession;
HINTERNET hConnect;
HINTERNET hRequest;
const CHAR *lpszAcceptTypes = "*/*" ;
CHAR szServername[256]="www.******.com";
CHAR szObjectname[100]="***.exe";
INTERNET_PORT wPort = 80;
LPTSTR lpszAgent = NULL; lpszAgent = GetFileName(argv[0]);
hSession = InternetOpen(lpszAgent,INTERNET_OPEN_TYPE_PRECONFIG,NULL,NULL,0);
if (hSession == NULL) 
{
ShowError("InternetOpen");
return -1;
}
hConnect = InternetConnect(hSession,szServername,wPort/*INTERNET_DEFAULT_HTTP_PORT*/,NULL,NULL,INTERNET_SERVICE_HTTP,0,0);
if (hConnect == NULL)
{
ShowError("InternetConnect");
return -2;
}
hRequest = HttpOpenRequest(hConnect,"GET",szObjectname,NULL,NULL,&lpszAcceptTypes,INTERNET_FLAG_RELOAD,0);
if (hRequest == NULL)
{
ShowError("HttpOpenRequest");
return -3;
}
//CHAR szHttpHeader[256] = "Host: ***********\r\n";
//BOOL bRetSend = HttpSendRequest(hRequest,szHttpHeader,strlen(szHttpHeader),NULL,0);
BOOL bRetSend = HttpSendRequest(hRequest,NULL,0,NULL,0);
if (bRetSend == FALSE)
{
ShowError("HttpSendRequest");
return -4;
}
DWORD dwIndex=0;
CHAR    szBuffer[32] = {0};
DWORD dwBufferLen=32; BOOL bRetQueryInfo = HttpQueryInfo(hRequest,HTTP_QUERY_CONTENT_LENGTH,szBuffer,&dwBufferLen,&dwIndex);
DWORD dwFileSize = (DWORD)atol(szBuffer) ;
if (bRetQueryInfo == FALSE)
{
ShowError("HttpQueryInfo");
return -5;
}
//CreateThread()
}void usage()
{
printf("Code by shocker<[email protected]>");
printf("Usage:\n");
}LPTSTR GetFileName(LPCTSTR lpszFilePath)
{
LPTSTR p;
p = strrchr(lpszFilePath, '\\');
if (p) {
p++;
}
else {
p = (CHAR *)lpszFilePath;
}
return p;
}void ShowError(LPCSTR lpszFuntionName)
{
DWORD nError;
nError = GetLastError();
printf("%s Error! GetLastError return:%d\n",lpszFuntionName,nError);
}但是不知道为什么,当我调用HttpQueryInfo(hRequest,HTTP_QUERY_CONTENT_LENGTH,szBuffer,&dwBufferLen,&dwIndex);这个时总是不能正确返回文件的大小,每次都返回20.....
我可以确定要下载的文件存在,并且路径没错

解决方案 »

  1.   

    这样就ok了?是不是还应该在前面添加添加:
    #pragma comment(lib,"wininet.lib")
      

  2.   

    BOOL CNUQ_HTTP::GetURL(const CString &strURL, 
     const CString &strFile, BYTE byTo)
    {
    BOOL br = FALSE;
    CInternetSession session("VCON_GETURL",PRE_CONFIG_INTERNET_ACCESS);
    CHttpConnection * pConnection = NULL;
    CHttpFile * pFile = NULL;
    // CStdioFile * pFile = NULL;
    DWORD dwRet = 0;
    INT nFileLen = 0;
    INT nRead = 0;
    INT nPos = 0;
    DWORD dwHttpRequestFlags=
    INTERNET_FLAG_EXISTING_CONNECT  
    | INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTP
    | INTERNET_FLAG_RELOAD;
    CFile LocalFile; //存储到本地的文件 LocalFile.m_hFile = NULL;
    m_nFileLen = 0; ReleaseBuf();
    try
    {
    CString s = "";
    s.Format("%d",m_shortPort); pConnection = session.GetHttpConnection(m_strServer,
    (WORD)m_shortPort,NULL,NULL);
    }catch(CInternetException* pEx)
        {
            pEx->Delete();
    goto CLEAR;
    }
    if (NULL == pConnection) goto CLEAR; try
    {
    pFile = pConnection->OpenRequest(
    CHttpConnection::HTTP_VERB_GET,strURL,NULL,1,NULL,NULL,
    dwHttpRequestFlags);
    pFile->SendRequest();
    pFile->QueryInfoStatusCode(dwRet);
    if(dwRet==HTTP_STATUS_OK)
    {
    try
    {
    nFileLen = pFile->SeekToEnd();
    pFile->SeekToBegin();
    if (nFileLen <= 0) goto CLEAR;

    }
    catch(CInternetException* pEx)
    {
    pEx->Delete();
    }
    catch(...)
    {
    }
    #define PER_READ_SIZE (3 * 1024)
    nPos = 0;
    if (GETURL_TO_MEM == byTo)
    {
    if (nFileLen > 0) 
    {
    m_pszbuf = new char[PER_READ_SIZE + nFileLen];
    do
    {
    nRead = pFile->Read(m_pszbuf + nPos,PER_READ_SIZE);
    nPos += nRead;
    }while(nRead > 0);
    }
    else //<out>无法读取长度
    {
    CString strread = "";
    m_pszbuf = new char[PER_READ_SIZE + 2];
    do
    {
    nRead = pFile->Read(m_pszbuf,PER_READ_SIZE);
    m_pszbuf[nRead] = '\0';
    if (nRead > 0) strread += CString(m_pszbuf);
    }while(nRead > 0);
    //<out>删除临时内存
    delete []m_pszbuf;
    m_pszbuf = NULL;
    nPos  = strread.GetLength(); 
    m_pszbuf = new char[nPos + 2];
    strcpy(m_pszbuf,(LPCSTR)strread);
    }
    }
    else if (GETURL_TO_FILE == byTo && "" != strFile)
    {
    m_pszbuf = new char[PER_READ_SIZE + 1];
    if (LocalFile.Open(strFile,CFile::modeCreate 
    | CFile::modeWrite | CFile::typeBinary))
    {
    do
    { //<out>读取数据
    nRead = pFile->Read(m_pszbuf,PER_READ_SIZE);
    //<out>写入本地文件
    if (nRead > 0)
    {
    LocalFile.Write(m_pszbuf,nRead);
    }
    nPos += nRead;
    }while(nRead > 0);
    LocalFile.Close();
    }
    ReleaseBuf();
    }
    m_nFileLen = nPos;
    br = TRUE;
    }
    }catch(CInternetException* pEx)
        {
            pEx->Delete();
    goto CLEAR;
    }
    CLEAR:
    if (NULL != pFile)
    {
    pFile->Close();
    delete pFile;
    pFile = NULL;
    }
    if (NULL != pConnection)
    {
    pConnection->Close();
    delete pConnection;
    pConnection = NULL;
    }
    session.Close();
    return br;
    }