C++ C++;下载文件WinInet-写入文件的0kb
有人能告诉我我的代码有什么问题吗 我正在尝试使用WinInet从internet下载一个文件。这个函数可以很好地连接到目标站点,我不明白为什么这个代码不起作用。有人能帮我吗 这是我的密码:C++ C++;下载文件WinInet-写入文件的0kb,c++,winapi,wininet,C++,Winapi,Wininet,有人能告诉我我的代码有什么问题吗 我正在尝试使用WinInet从internet下载一个文件。这个函数可以很好地连接到目标站点,我不明白为什么这个代码不起作用。有人能帮我吗 这是我的密码: HANDLE hFile = CreateFileW(FilePath, GENERIC_WRITE, NULL, NULL, CREATE_ALWAYS, NULL, NULL); if (hFile != INVALID_HANDLE_VALUE || GetLastError() == ERROR_AL
HANDLE hFile = CreateFileW(FilePath, GENERIC_WRITE, NULL, NULL, CREATE_ALWAYS, NULL, NULL);
if (hFile != INVALID_HANDLE_VALUE || GetLastError() == ERROR_ALREADY_EXISTS)
{
CHAR Buffer[2048];
DWORD BytesRead=0, BytesToRead=0;
DWORD BytesWritten=0, BytesToWrite=0;
SetFilePointer(hFile, 0, 0, FILE_BEGIN);
do
{
if (BytesRead)
{
WriteFile(hFile, Buffer, BytesWritten, &BytesToWrite, FALSE);
}
}
while
(InternetReadFile(hRequest, (LPVOID)Buffer, BytesToRead, &BytesRead) != FALSE);
}
CloseHandle(hFile);
}
hRequest被传递给函数,它是来自HttpOpenRequestA的HINTERNET句柄。您的代码有一些逻辑问题
CreateFileW()
时,您误用了GetLastError()
。无论文件是否已存在,CreateFileW()
如果成功创建/打开文件,则不会返回无效的\u句柄。这就是您需要检查的全部内容(仅当CreateFileW()
失败并且您想找出原因时,才调用GetLastError()
)。此外,根本不需要调用SetFilePointer()
,因为CREATE\u ALWAYS
确保打开的文件是空的,如果文件已经存在并且其中包含数据,则截断该文件
do..while
循环应改为while
循环,以便首先调用InternetReadFile()
。在第一次循环迭代中跳过WriteFile()
没有意义。如果使用do..while
循环,则不应将InternetReadFile()
用作循环条件InternetReadFile()
出现错误失败时,您才会中断循环。您希望它在到达响应末尾时失败,但它实际上返回TRUE并将BytesRead
设置为0。这是记录在案的行为,您根本不需要处理:
InternetReadFile的操作与基本ReadFile函数非常相似,只有少数例外。通常,InternetReadFile从一个HINTERNET句柄中检索数据,作为一个连续的字节流。每次调用InternetReadFile时要读取的数据量由dwNumberOfBytesToRead参数指定,数据在lpBuffer参数中返回。正常读取为每次调用InternetReadFile检索指定的dwNumberOfBytesToRead,直到到达文件末尾为确保检索到所有数据,应用程序必须继续调用InternetReadFile函数,直到函数返回TRUE且lpdwNumberOfBytesRead参数等于零。如果请求的数据写入缓存,这一点尤其重要,因为否则缓存将无法正确更新,下载的文件也不会提交到缓存。请注意,除非打开数据流的原始请求设置了INTERNET\u标志\u否\u缓存\u写入标志,否则缓存将自动进行
当同步读取操作到达文件末尾时,ReadFile返回TRUE并将*lpNumberOfBytesRead设置为零
WriteFile()
时,您将BytesWrite
传递给nNumberOfBytesToWrite
参数,但BytesWrite
从未设置为0以外的任何值,因此不会写入文件。您需要通过字节读取
HANDLE hFile = CreateFileW(FilePath, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_FLAG_SEQUENTIAL_SCAN, NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
// handle error as needed...
}
else
{
BYTE Buffer[2048];
DWORD BytesRead, BytesWritten;
do
{
if (!InternetReadFile(hRequest, Buffer, sizeof(Buffer), &BytesRead))
{
// handle error as needed...
break;
}
if (!BytesRead)
break;
if (!WriteFile(hFile, Buffer, BytesRead, &BytesWritten, FALSE))
{
// handle error as needed...
break;
}
}
while (true);
CloseHandle(hFile);
}
MSDN甚至有一个关于如何使用InternetReadFile()
的完整示例:
BOOL GetFile(霍本的HINTERNET,//来自InternetOpen()的句柄)
CHAR*szUrl,//完整URL
CHAR*szFileName)//本地文件名
{
DWORD dwSize;
CHAR szHead[]=“接受:*/\r\n\r\n”;
VOID*szTemp[25];
腹地连接;
文件*pFile;
如果(!(hConnect=InternetOpenUrl(霍本、szUrl、szHead、,
lstrlen(szHead),互联网(标志不缓存,0))
{
cerr可能重复您从未将bytesWrite
设置为0
以外的任何内容(另外,您在WriteFile
调用中交换了bytesWrite
和BytesToWrite
的名称)但除此之外,代码的其余部分看起来不错?如果您修复它至少应该写入数据:)您的第一个If
-子句没有意义。如果最后一个错误代码设置为error\u ready\u EXISTS
,则可能会写入由句柄INVALID\u handle\u VALUE
标识的文件,即您没有写入我不明白MSDN的例子。什么是void*szTemp[25]
?指向字节数组的指针?它没有分配,然后在调用InternetReadFile时读取50个字节(hConnect,szTemp,50,&dwSize)
他们似乎是故意这么做的,他们甚至对此发表评论。@BarmakShemirani:这很好。在MSDN的第一个例子中,VOID*szTemp[25];
需要是BYTE szTemp]50];
而在他们的第二个例子中,TCHAR sz[1024];
需要是BYTE sz[1024];
相反。我已将这些更改提交给Microsoft。
BOOL GetFile (HINTERNET IN hOpen, // Handle from InternetOpen()
CHAR *szUrl, // Full URL
CHAR *szFileName) // Local file name
{
DWORD dwSize;
CHAR szHead[] = "Accept: */*\r\n\r\n";
VOID * szTemp[25];
HINTERNET hConnect;
FILE * pFile;
if ( !(hConnect = InternetOpenUrl ( hOpen, szUrl, szHead,
lstrlen (szHead), INTERNET_FLAG_DONT_CACHE, 0)))
{
cerr << "Error !" << endl;
return 0;
}
if ( !(pFile = fopen (szFileName, "wb" ) ) )
{
cerr << "Error !" << endl;
return FALSE;
}
do
{
// Keep coping in 25 bytes chunks, while file has any data left.
// Note: bigger buffer will greatly improve performance.
if (!InternetReadFile (hConnect, szTemp, 50, &dwSize) )
{
fclose (pFile);
cerr << "Error !" << endl;
return FALSE;
}
if (!dwSize)
break; // Condition of dwSize=0 indicate EOF. Stop.
else
fwrite(szTemp, sizeof (char), dwSize , pFile);
} // do
while (TRUE);
fflush (pFile);
fclose (pFile);
return TRUE;
}