通过 WinInet 下载数据

Posted

技术标签:

【中文标题】通过 WinInet 下载数据【英文标题】:Downloading data via WinInet 【发布时间】:2017-11-25 12:59:47 【问题描述】:

所以有一个代码,可以下载大小不大于 1024*100 字节的数据。代码来自https://rsdn.org/article/inet/inetapi.xml。

据我了解,InternetReadFile 在每次调用之后都应该继续读取字符数,否则它毫无意义,因为它会返回相同的数据。我红色,有一个函数,可以移动读取开始指针。我要使用它吗?

HINTERNET hInternetSession;
HINTERNET hURL;
char cBuffer[1024*100];            // I'm only going to access 1K of info.
BOOL bResult;
DWORD dwBytesRead;

// Make internet connection.
hInternetSession = InternetOpen(
    L"tes", // agent
    INTERNET_OPEN_TYPE_PRECONFIG,  // access
    NULL, NULL, 0);                // defaults

// Make connection to desired page.
hURL = InternetOpenUrl(
    hInternetSession,                       // session handle
    L"https://www.google.com.ua/images/branding/googlelogo/1x/googlelogo_color_272x92dp.png",  // URL to access
    NULL, 0, 0, 0);                         // defaults

// Read page into memory buffer.
while(bResult = InternetReadFile(
    hURL,              // handle to URL
    (LPSTR)cBuffer,    // pointer to buffer
    (DWORD)1024 * 100,       // size of buffer
    &dwBytesRead)==TRUE&&dwBytesRead>0) // pointer to var to hold return value

// Close down connections.
InternetCloseHandle(hURL);
InternetCloseHandle(hInternetSession);

DWORD dwTemp;
HANDLE hFile = CreateFile(L"googlelogo_color_272x92dp.png", GENERIC_WRITE, 0, NULL,
    CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (INVALID_HANDLE_VALUE == hFile) 
    return 0;

WriteFile(hFile, cBuffer, sizeof(cBuffer), &dwTemp, NULL);

问题:我无法读取超过 1024*1024 字节,程序崩溃,当创建 char[1024*1024]

【问题讨论】:

char[1024*1024] - 这是函数中的局部变量吗? @RbMm,是的,都是本地的 所以你想要什么 - 默认堆栈大小为 1Mb - 这个数组吃掉所有堆栈,结果堆栈溢出 @RbMm,我想加载大于 100 kb 的数据 让 char cBuffer global 解决了这个问题 - 真的只说你在主题上的低技能。从哪里开始知道文件大小?如果您的硬编码大小缓冲区很大怎么办? 【参考方案1】:

这是一个完整的程序。感谢@RbMm

#include <windows.h>
#include <wininet.h>

#pragma comment(lib,"wininet")


int main(int argc, char* argv[])

HINTERNET hInternetSession;
HINTERNET hURL;
            // I'm only going to access 1K of info.
BOOL bResult;
DWORD dwBytesRead=1;

// Make internet connection.
hInternetSession = InternetOpen(
    L"tes", // agent
    INTERNET_OPEN_TYPE_PRECONFIG,  // access
    NULL, NULL, 0);                // defaults

// Make connection to desired page.
hURL = InternetOpenUrl(
    hInternetSession,                       // session handle
    L"http://wallpapers-images.ru/1920x1080/nature/wallpapers/wallpapers-nature-1.jpg",  // URL to access
    NULL, 0, 0, 0);                         // defaults

// Read page into memory buffer.

char buf[1024];

DWORD dwTemp;
HANDLE hFile = CreateFile(L"пример.jpg", GENERIC_WRITE, 0, NULL,
    CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);

if (INVALID_HANDLE_VALUE == hFile) 
    return 0;


for (;dwBytesRead>0;)

    InternetReadFile(hURL, buf, (DWORD)sizeof(buf), &dwBytesRead);
    WriteFile(hFile, buf, dwBytesRead, &dwTemp, NULL);


// Close down connections.
InternetCloseHandle(hURL);
InternetCloseHandle(hInternetSession);

CloseHandle(hFile);


return 0;

【讨论】:

在调用 InternetReadFile 时使用 sizeof(buf) 而不是 (DWORD)1023(为什么不使用 1024?)。你在开始buf[1024] = ; 时不需要零初始化缓冲区是为了什么?!并始终检查 InternetReadFileWriteFile 的返回值以了解错误时的中断循环 @RbMm,好的,我会改的 只需做while ( InternetReadFile(..,&amp;dwBytesRead) &amp;&amp; dwBytesRead &amp;&amp; WriteFile(..,dwBytesRead,..) ) ; @RbMm 这种写法让我不舒服 @RbMm 风格不好。最好单独检查每个函数的返回值,以便我们知道哪个函数失败了。

以上是关于通过 WinInet 下载数据的主要内容,如果未能解决你的问题,请参考以下文章

使用wininet与服务器交换数据

Delphi - 使用 Wininet 下载文件?

使用wininet下载文件时如何避免冻结

WinInet 只下载网页的一部分

Delphi用WinInet用用户名和密码下载文件

使用 Wininet 下载二进制文件