Альтернатива .NET WebClient.DownloadData (url) в C ++ / WinAPI? - PullRequest
0 голосов
/ 30 марта 2011

Как я могу получить содержимое файла онлайн с C ++?

Ответы [ 2 ]

2 голосов
/ 30 марта 2011

Есть несколько способов сделать это.

WinInet

Во-первых, в Windows есть встроенный API, позволяющий делать HTTP-запросы, который достаточно прост в использовании. Я использую этот простой класс-обертку для загрузки файлов, используя его:

/**
 * Simple wrapper around the WinInet library.
 */
class Inet
{
public:
    explicit Inet() : m_hInet(NULL), m_hConnection(NULL)
    {
        m_hInet = ::InternetOpen(
            "My User Agent",
            INTERNET_OPEN_TYPE_PRECONFIG,
            NULL,
            NULL,
            /*INTERNET_FLAG_ASYNC*/0);
    }

    ~Inet()
    {
        Close();

        if (m_hInet)
        {
            ::InternetCloseHandle(m_hInet);
            m_hInet = NULL;
        }
    }

    /**
     * Attempt to open a URL for reading.
     * @return false if we don't have a valid internet connection, the url is null, or we fail to open the url, true otherwise.
     */
    bool Open(LPCTSTR url)
    {
        if (m_hInet == NULL)
        {
            return false;
        }

        if (url == NULL)
        {
            return false;
        }

        m_hConnection = ::InternetOpenUrl(
            m_hInet,
            url,
            NULL /*headers*/,
            0 /*headers length*/,
            INTERNET_FLAG_NO_AUTH | INTERNET_FLAG_NO_CACHE_WRITE | INTERNET_FLAG_NO_COOKIES | INTERNET_FLAG_NO_UI, 
            reinterpret_cast<DWORD_PTR>(this));

        return m_hConnection != NULL;
    }

    /**
     * Read from a connection opened with Open.
     * @return true if we read data.
     */
    bool ReadFile(LPVOID lpBuffer, DWORD dwNumberOfBytesToRead, LPDWORD dwRead)
    {
        ASSERT(m_hConnection != NULL);

        return ::InternetReadFile(m_hConnection, lpBuffer, dwNumberOfBytesToRead, dwRead) != 0;
    }

    /**
     * Close any open connection.
     */
    void Close()
    {
        if (m_hConnection != NULL)
        {
            ::InternetCloseHandle(m_hConnection);
            m_hConnection = NULL;
        }
    }

private:
    HINTERNET m_hInet;
    HINTERNET m_hConnection;
};

Использование этого очень просто:

Inet inet;
if (inet.Open(url))
{
    BYTE buffer[UPDATE_BUFFER_SIZE];
    DWORD dwRead;
    while (inet.ReadFile(&buffer[0], UPDATE_BUFFER_SIZE, &dwRead))
    {
        // TODO: Do Something With buffer here
        if (dwRead == 0)
        {
            break;
        }
    }
}

Libcurl

Если вы предпочитаете избегать специфичных для Windows API-интерфейсов, вы могли бы сделать намного хуже, чем использовать библиотеку libcurl для получения файлов с использованием различных протоколов, включая HTTP. Вот хороший пример, показывающий, как получить URL-адрес непосредственно в память (избегая загрузки на диск): образец getinmemory .

0 голосов
/ 30 марта 2011

Используйте следующие функции.

WinHttpConnect
WinHttpOpenRequest
WinHttpSendRequest
WinHttpReceiveResponse
WinHttpQueryDataAvailable
WinHttpReadData
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...