C++ URL下载文件到内存

C++ URL下载文件到内存,c++,wininet,C++,Wininet,我正在使用URLDownloadToFile将图像从web服务器下载到桌面上的一个目录中。如果我不想将图像保存到磁盘,而是想将它们像字节数组或base64字符串之类读入内存,那么有没有类似于URLDownloadToFile的函数可以实现这一点?Win32 API中没有像URLDownloadToFile那样为文件下载URL资源到内存中的单个do all函数。您必须编写自己的函数来请求URL,然后将数据读入内存 例如,使用或/,然后。有关更多详细信息,请参阅MSDN上的 或者使用您选择的任何其他

我正在使用URLDownloadToFile将图像从web服务器下载到桌面上的一个目录中。如果我不想将图像保存到磁盘,而是想将它们像字节数组或base64字符串之类读入内存,那么有没有类似于URLDownloadToFile的函数可以实现这一点?

Win32 API中没有像URLDownloadToFile那样为文件下载URL资源到内存中的单个do all函数。您必须编写自己的函数来请求URL,然后将数据读入内存

例如,使用或/,然后。有关更多详细信息,请参阅MSDN上的

或者使用您选择的任何其他HTTP/S库/API。

有,允许您下载到内存中

从这三个方面来看,它似乎是最容易使用的,因为它返回一个IStream指针,您可以在循环中同步读取该指针。虽然它不像URLDowloadToFile那样是一个单一的全能函数,但使用起来并不困难

下面是一个完整的控制台应用程序示例。它从URL下载并将响应写入标准输出。与此相反,您可以将响应存储在std::vector中,或者对其执行任何您喜欢的操作

#include <Windows.h>
#include <Urlmon.h>   // URLOpenBlockingStreamW()
#include <atlbase.h>  // CComPtr
#include <iostream>
#pragma comment( lib, "Urlmon.lib" )

struct ComInit
{
    HRESULT hr;
    ComInit() : hr( ::CoInitialize( nullptr ) ) {}
    ~ComInit() { if( SUCCEEDED( hr ) ) ::CoUninitialize(); } 
};

int main(int argc, char* argv[])
{
    ComInit init;

    // use CComPtr so you don't have to manually call Release()
    CComPtr<IStream> pStream;  

    // Open the HTTP request.
    HRESULT hr = URLOpenBlockingStreamW( nullptr, L"http://httpbin.org/headers", &pStream, 0, nullptr );
    if( FAILED( hr ) )
    {
        std::cout << "ERROR: Could not connect. HRESULT: 0x" << std::hex << hr << std::dec << "\n"; 
        return 1;
    }

    // Download the response and write it to stdout.
    char buffer[ 4096 ];
    do
    {
        DWORD bytesRead = 0;
        hr = pStream->Read( buffer, sizeof(buffer), &bytesRead );

        if( bytesRead > 0 )
        {
            std::cout.write( buffer, bytesRead );
        }
    } 
    while( SUCCEEDED( hr ) && hr != S_FALSE );

    if( FAILED( hr ) )
    {
        std::cout << "ERROR: Download failed. HRESULT: 0x" << std::hex << hr << std::dec << "\n";
        return 2;
    }

    std::cout << "\n";

    return 0;
}

“错了,请看我的答案。@zett42:但这并不是一个完全类似于URLDownloadToFile的函数。”。您必须首先打开一个流,然后从该流中读取。这些都是单独的操作,因此与我的回答没有什么不同,只是使用了不同的API。请注意,我说过没有像URLDownloadToFile…这样的“全部完成”函数,这是真的。全部完成的函数应该是URLOpenStream,我刚刚选择URLOpenBlockingStream作为更简单的示例。@zett42:URLOpenStream几乎不是一个“全部完成”函数,因为它需要调用方传入一个单独的IBindStatusCallback对象来处理OnDataAvailable回调,并且数据是以STDMEDIUM格式提供的,这需要额外的函数调用来提取数据,因为它可以是HGLOBAL、IStream或IStorage格式。do all函数是这样一个函数,其中调用者只需传入URL和内存块或输出流,并且该函数完全填充输出,而不需要调用者做任何工作。没有一个Win32 API函数可以做到这一点。我明白这一点。