请看下面的代码(是一个出自Codeguru的标准函数)CString GetFile(const char *url, const char *filename)
{
#define HTTPBUFLEN    512 // Size of HTTP Buffer...
char httpbuff[HTTPBUFLEN];
TCHAR   szCause[255];
CString Cause;
Cause.Format("YES"); TRY
{
CInternetSession mysession;
CStdioFile *remotefile = mysession.OpenURL(url,1,INTERNET_FLAG_TRANSFER_BINARY|INTERNET_FLAG_RELOAD); CFile myfile(filename, CFile::modeCreate|CFile::modeWrite|CFile::typeBinary);
int numbytes;///////////////////////////////////////////////////////////////////////
                   这里的缓冲区HTTPBUFLEN现在设为512个字节(设成其它的也一样)每次读取的数据是HTTPBUFLEN个字节,当所读取的文件剩下的字节数小于HTTPBUFLEN时,也就是最后一次调remotefile->Read时,remotefile->Read这句调用就阻塞住了,换不同的文件,不同大小,不同的缓冲区设置,都是这样的情况,屡试不爽。当前系统是2000,换另外一个98系统,一点问题都没有,文件顺利下载,回到2000,又是下载到最后的时候阻塞住了。另外还试了CHttpFile和InternetReadFile等其他的方法来下载文件,也都是这个问题:在最后一次Read的时候阻塞住了!有谁遇到过这样的情况?为什么另一个98系统下面都没有问题?高分请教!
 #############问题出在下面这句话这里
///////////////////////////////////////////////////////////////////////
while (numbytes = remotefile->Read(httpbuff, HTTPBUFLEN))
   myfile.Write(httpbuff, numbytes); remotefile->Close(); 
mysession.Close(); 
} CATCH_ALL(error)
{
error->GetErrorMessage(szCause,254,NULL);
Cause.Format("%s",szCause);
}
END_CATCH_ALL; return (Cause);
}

解决方案 »

  1.   

    WinInet的MFC我倒是没用过,我用的是API,没出现你这样的情况。下面是我的一段代码:
    do
    {
    if(InternetReadFile(pDlg->m_hRequest,pBuffer,2048,&dwDownload)==FALSE)
    throw(0);
    fileUpdate.Write(pBuffer,dwDownload);
    dwTotal+=dwDownload;
    PostMessage(pDlg->GetSafeHwnd(),WM_UPDATE_STATUS,STATUS_DOWNLOAD_IN_PROGRESS,dwTotal);
    }while(dwTotal<struInfo.nFileSize);运行很正常,系统是2000这个程序是从我那个Norton病毒库自动更新程序上Copy下来的,如果你要的话,你可以到我的网站上下载,或者给我发消息,我给你发到邮箱里。
      

  2.   

    试试:1 CInternetFile *remotefile = mysession.OpenURL(url,1,INTERNET_FLAG_TRANSFER_BINARY);2 while (true)
     {
        numbytes = remotefile->Read(httpbuff, HTTPBUFLEN)
        myfile.Write(httpbuff, numbytes);
        if(numbytes < HTTPBUFLEN) break;
      }
      

  3.   

    sxbyl(山野白菜) : 我也试了InternetReadFile,还是一样的问题,读到最后就死了
     freelybird(阿愚) :试了一下,问题照旧 :(
      

  4.   

    不会吧?那你先读一个本机网站上的文件试试?那你读一个本机文件试试?我的程序下载HTML文件和二进制文件都没有任何问题啊。
      

  5.   

    http://www.codeproject.com/useritems/get_remote_file.asp
      

  6.   

    http://www.mindcracker.com/mindcracker/c_cafe/wininet.asp
      

  7.   

    问题在于
    while (numbytes = remotefile->Read(httpbuff, HTTPBUFLEN))
    {
          myfile.Write(httpbuff, numbytes);
          remotefile->Close(); 
          mysession.Close(); 
    }
    既然最后一次阻塞了,也就是最后一次能读取的文件长度小于HTTPBUFLEN.所以阻塞了,所以你可以取出下载文件总长度,每次调用remotefile->Read的时候比较一下:
    int fileSize = remotefile->GetLength();
    int size = (fizeSize < HTTPBUFLEN)? fileSize:HTTPBUFLEN;
    int readSize=0;
    while (numbytes = remotefile->Read(httpbuff, size))
    {
          readSize += numbytes;
          myfile.Write(httpbuff, numbytes);
          int leftSize = fileSize - readSize;
          size = (leftSize < HTTPBUFLEN)? leftSize:HTTPBUFLEN;
    }
    remotefile->Close(); 
    mysession.Close(); 
      

  8.   

    2 mty:但我的程序中没有用这种方法也是运行很好啊,从没出现过阻塞的现象。
      

  9.   

    bool SaveUrl(LPCTSTR url, LPCTSTR filename)
    {
    cout<<"SaveUrl("<<url<<","<<filename<<")"<<endl;
    HINTERNET hUrlFile = ::InternetOpenUrl(g_hNet,url,NULL,0,INTERNET_FLAG_RELOAD,0) ;
    // Get the length of the file.            
    char bufQuery[32] ;
    DWORD dwLengthBufQuery = sizeof(bufQuery);
    BOOL bQuery = ::HttpQueryInfo(hUrlFile,
      HTTP_QUERY_CONTENT_LENGTH, 
      bufQuery, 
      &dwLengthBufQuery,NULL) ;
    // Convert length from ASCII string to a DWORD.
    DWORD dwFileSize = (DWORD)atol(bufQuery) ;
    char buffer[16*1024] ;
    DWORD dwBytesRead = 1;
    DWORD dw_total_read=0;
    BOOL bRead=TRUE;
    fstream file;
    //if(dwFileSize>32*1024)
    {
    file.open(filename,ios::out|ios::binary,filebuf::sh_read);
    while(bRead&&dwBytesRead>0)
    {
    bRead = ::InternetReadFile(hUrlFile,buffer, sizeof(buffer), &dwBytesRead);
    if(dwBytesRead>0)
    {
    file.write(buffer,dwBytesRead);
    dw_total_read +=dwBytesRead;
    }
    }
    file.flush();
    file.close();
    }
    ::InternetCloseHandle(hUrlFile) ;
    return dwFileSize==dw_total_read;
    }
      

  10.   

    I define a global HINTERNET and open it 
    g_hNet = ::InternetOpen("Outlook",PRE_CONFIG_INTERNET_ACCESS, NULL,INTERNET_INVALID_PORT_NUMBER,0) ;
    before call SaveUrl
      

  11.   

    试了一下 mty(天鱼) 的方法:我要下载的文件的长度是828个字节:
    int fileSize = 828;
    int size = (fileSize < HTTPBUFLEN)? fileSize:HTTPBUFLEN;
    int readSize=0;
    while (numbytes = remotefile->Read(httpbuff, size))
    {
      readSize += numbytes;
      myfile.Write(httpbuff, numbytes);
      int leftSize = fileSize - readSize;
      size = (leftSize < HTTPBUFLEN)? leftSize:HTTPBUFLEN;
    }在最后一次读取的时候还是阻塞了!改成这样,少读一个字节,就没有问题!
    int fileSize = 827;
    int size = (fileSize < HTTPBUFLEN)? fileSize:HTTPBUFLEN;
    int readSize=0;
    while (numbytes = remotefile->Read(httpbuff, size))
    {
      readSize += numbytes;
      myfile.Write(httpbuff, numbytes);
      int leftSize = fileSize - readSize;
      size = (leftSize < HTTPBUFLEN)? leftSize:HTTPBUFLEN;
    } remotefile->Seek(827,CInternetFile::begin);
    remotefile->Read(httpbuff,1);
    myfile.Write(httpbuff, 1);然后想尝试单独读取最后一个字节
    remotefile->Seek(827,CInternetFile::begin);
    remotefile->Read(httpbuff,1);
    myfile.Write(httpbuff, 1);
    在Read那句又阻塞了!看来是最后一个字节的问题,怎么解释呢?
      

  12.   

    masterz() 的方法也试过了,到Read那里直接就阻塞了,因为一开始就读到了最后一个字节
      

  13.   

    干脆用 socket写 好了,现在我们项目里的get/post,pop3,smtp...都是在unix下用socket 函数写的,挺好用,好控制,不过http文件下载没有写过。偶好久没有摸inet或者mfc了。