该文档做了以下评论:
InternetReadFile的操作与基本的ReadFile函数非常相似,只有少数例外.通常,InternetReadFile从HINTERNET句柄中检索数据作为连续的字节流.每次调用InternetReadFile时要读取的数据量由dwNumberOfBytesToRead参数指定,数据在lpBuffer参数中返回.正常读取为每次调用InternetReadFile检索指定的dwNumberOfBytesToRead,直到到达文件末尾.为确保检索所有数据,应用程序必须继续调用InternetReadFile函数,直到函数返回TRUE且lpdwNumberOfBytesRead参数等于零.
基本上,不能保证读取的功能完全正确dwNumberOfBytesToRead.检查使用lpdwNumberOfBytesRead参数实际读取的字节数.
此外,只要文件总大小超过dwNumberOfBytesToRead,您就需要多次调用该调用.因为它不能dwNumberOfBytesToRead一次读取多次.
如果您预先拥有总文件大小,则循环采用以下形式:
::DWORD error = ERROR_SUCCESS;
::BYTE data[SIZE]; // total file size.
::DWORD size = 0;
::DWORD read = 0;
do {
::BOOL result = ::InternetReadFile(stream, data+size, SIZE-size, &read);
if ( result == FALSE ) {
error = ::GetLastError();
}
}
while ((error == ERROR_SUCCESS) && (read > 0) && ((size+=read) < SIZE));
// check that `SIZE` was correct.
if (size != SIZE) {
}
Run Code Online (Sandbox Code Playgroud)
如果没有,那么您需要将缓冲区中的数据写入另一个文件而不是累积它.
编辑(样本测试计划):
这是一个完整的程序,可以获取StackOverflow的首页.这将以1K块的形式下载大约200K的HTML代码,并检索整个页面.你可以运行它,看它是否有效?
#include <Windows.h>
#include <Wininet.h>
#include <iostream>
#include <fstream>
namespace {
::HINTERNET netstart ()
{
const ::HINTERNET handle =
::InternetOpenW(0, INTERNET_OPEN_TYPE_DIRECT, 0, 0, 0);
if ( handle == 0 )
{
const ::DWORD error = ::GetLastError();
std::cerr
<< "InternetOpen(): " << error << "."
<< std::endl;
}
return (handle);
}
void netclose ( ::HINTERNET object )
{
const ::BOOL result = ::InternetCloseHandle(object);
if ( result == FALSE )
{
const ::DWORD error = ::GetLastError();
std::cerr
<< "InternetClose(): " << error << "."
<< std::endl;
}
}
::HINTERNET netopen ( ::HINTERNET session, ::LPCWSTR url )
{
const ::HINTERNET handle =
::InternetOpenUrlW(session, url, 0, 0, 0, 0);
if ( handle == 0 )
{
const ::DWORD error = ::GetLastError();
std::cerr
<< "InternetOpenUrl(): " << error << "."
<< std::endl;
}
return (handle);
}
void netfetch ( ::HINTERNET istream, std::ostream& ostream )
{
static const ::DWORD SIZE = 1024;
::DWORD error = ERROR_SUCCESS;
::BYTE data[SIZE];
::DWORD size = 0;
do {
::BOOL result = ::InternetReadFile(istream, data, SIZE, &size);
if ( result == FALSE )
{
error = ::GetLastError();
std::cerr
<< "InternetReadFile(): " << error << "."
<< std::endl;
}
ostream.write((const char*)data, size);
}
while ((error == ERROR_SUCCESS) && (size > 0));
}
}
int main ( int, char ** )
{
const ::WCHAR URL[] = L"http://stackoverflow.com/";
const ::HINTERNET session = ::netstart();
if ( session != 0 )
{
const ::HINTERNET istream = ::netopen(session, URL);
if ( istream != 0 )
{
std::ofstream ostream("output.txt", std::ios::binary);
if ( ostream.is_open() ) {
::netfetch(istream, ostream);
}
else {
std::cerr << "Could not open 'output.txt'." << std::endl;
}
::netclose(istream);
}
::netclose(session);
}
}
#pragma comment ( lib, "Wininet.lib" )
Run Code Online (Sandbox Code Playgroud)