>>>>>>>> 编写文件下载程序遇到的奇怪问题,高分请教~~~~~

silver 2002-07-23 01:13:55
请看下面的代码(是一个出自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);
}
...全文
72 15 打赏 收藏 转发到动态 举报
写回复
用AI写文章
15 条回复
切换为时间正序
请发表友善的回复…
发表回复
vcbear 2002-07-25
  • 打赏
  • 举报
回复
干脆用 socket写 好了,现在我们项目里的get/post,pop3,smtp...都是在unix下用socket 函数写的,挺好用,好控制,不过http文件下载没有写过。偶好久没有摸inet或者mfc了。
silver 2002-07-24
  • 打赏
  • 举报
回复
masterz() 的方法也试过了,到Read那里直接就阻塞了,因为一开始就读到了最后一个字节
silver 2002-07-24
  • 打赏
  • 举报
回复
试了一下 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那句又阻塞了!

看来是最后一个字节的问题,怎么解释呢?
masterz 2002-07-23
  • 打赏
  • 举报
回复
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
masterz 2002-07-23
  • 打赏
  • 举报
回复
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;
}
sxbyl 2002-07-23
  • 打赏
  • 举报
回复
2 mty:

但我的程序中没有用这种方法也是运行很好啊,从没出现过阻塞的现象。
mty 2002-07-23
  • 打赏
  • 举报
回复
问题在于
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();

COKING 2002-07-23
  • 打赏
  • 举报
回复
http://www.mindcracker.com/mindcracker/c_cafe/wininet.asp
COKING 2002-07-23
  • 打赏
  • 举报
回复
http://www.codeproject.com/useritems/get_remote_file.asp
nbgyf 2002-07-23
  • 打赏
  • 举报
回复
UP
sh210 2002-07-23
  • 打赏
  • 举报
回复
关注,up一下
sxbyl 2002-07-23
  • 打赏
  • 举报
回复
不会吧?那你先读一个本机网站上的文件试试?那你读一个本机文件试试?我的程序下载HTML文件和二进制文件都没有任何问题啊。
silver 2002-07-23
  • 打赏
  • 举报
回复
sxbyl(山野白菜) : 我也试了InternetReadFile,还是一样的问题,读到最后就死了


freelybird(阿愚) :试了一下,问题照旧 :(

freelybird 2002-07-23
  • 打赏
  • 举报
回复
试试:

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;
}
sxbyl 2002-07-23
  • 打赏
  • 举报
回复
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下来的,如果你要的话,你可以到我的网站上下载,或者给我发消息,我给你发到邮箱里。

16,472

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • Web++
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

试试用AI创作助手写篇文章吧