You might look for a file download solution so that you can create a software downloader or updater for you application. In this tutorial, i’ll show you how this can be done by using of C++. This tutorial will demonstrate how to download a ZIP file from the following URL link: http://www.askyb.com/wp-content/uploads/2012/09/hello.zip

1. Create a Win32 Console Application. I called this project “DownloadSample”.

2. Include header file to this project. Since this project is going to utilize Windows HTTP Services, we will need to include its header file to this project.

#include <windows.h>
#include <winhttp.h>

3. Make sure that we add linker options as well as Windows HTTP Services library names

#pragma comment(lib,"winhttp.lib")

4. In the _tmain() function, we start by obtaining the http session handle

1
2
3
4
5
6
7
8
9
10
11
12
   // Use WinHttpOpen to obtain a session handle
  HINTERNET hInternet = WinHttpOpen(L"Askyb Downloader",
                WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
                WINHTTP_NO_PROXY_NAME,
                WINHTTP_NO_PROXY_BYPASS,
                0);

  if(hInternet == NULL)
  {
    printf("Failed to initialize http session.\n");
    return 0;
  }

5. Once the http session handle is ready, we will now try to connect to the http server. I am using “www.askyb.com” as an example http server in this tutorial. You may change it to other http server. I am not connect to a server with SSL, so i am using INTERNET_DEFAULT_HTTP_PORT in this example. You may change it to INTERNET_DEFAULT_HTTPS_PORT if you try to connect to a server with SSL.

1
2
3
4
5
6
7
8
  // Specify an HTTP server
  HINTERNET hConnected = WinHttpConnect(hInternet, L"www.askyb.com", INTERNET_DEFAULT_HTTP_PORT, 0);

  if (hConnected == NULL)
  {
    WinHttpCloseHandle(hInternet);
    return 0;
  }

6. We now creates an HTTP request handle to the server. Make sure that we provide the correct url path to the third parameter in the WinHttpOpenRequest function.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
  // Create an HTTP Request handle
  HINTERNET hRequest = WinHttpOpenRequest(hConnected,
    L"GET",
    L"/wp-content/uploads/2012/09/hello.zip",
    NULL,
    WINHTTP_NO_REFERER,
    WINHTTP_DEFAULT_ACCEPT_TYPES,
    WINHTTP_FLAG_REFRESH );

  if (hRequest == NULL)
  {
    ::WinHttpCloseHandle(hConnected);
    ::WinHttpCloseHandle(hInternet);
    return 0;
  }

7. Once the http request is ready, we will send the request to http server now.

1
2
3
4
5
6
7
8
9
10
11
12
// Send a Request
  if(WinHttpSendRequest( hRequest,
      WINHTTP_NO_ADDITIONAL_HEADERS, 0,
      WINHTTP_NO_REQUEST_DATA, 0,
      0, 0) == FALSE)
  {
    DWORD err = GetLastError();
    WinHttpCloseHandle(hRequest);
    WinHttpCloseHandle(hConnected);
    WinHttpCloseHandle(hInternet);
    return 0;
  }

8. A successful response should be receive by our sample application from the http server after the http request was sent in step #6.

1
2
3
4
5
6
7
8
9
  // Receive a Response
  if (WinHttpReceiveResponse(hRequest, NULL) == FALSE)
  {
    DWORD err = GetLastError();
    WinHttpCloseHandle(hRequest);
    WinHttpCloseHandle(hConnected);
    WinHttpCloseHandle(hInternet);
    return 0;
  }

9. We can now start to create a file handle to hold the download data in later steps. I create a file called “hello.zip”.

1
2
  // Create a sample binary file
    HANDLE hFile = CreateFile(L"hello.zip", GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);

10. The download process will start now. This is a while loop where we check for available data from http server. Whenever the application receive the data from http server, it will write it the to hello.zip file that was created previously. The download will stop once there are no available data from the http server.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
  DWORD dwSize = 0;
  bool bRetValue = false;
  printf("Downloading ........");

  do
  {
    // Check for available data.
    if (!WinHttpQueryDataAvailable( hRequest, &dwSize))
    {
      printf("Data not available\n");
    }

    // Allocate space for the buffer.
    BYTE *pchOutBuffer = new BYTE[dwSize+1];
    if (!pchOutBuffer)
    {
      printf("Http Request is out of memory.\n");
      dwSize=0;
    }
    else
    {
      // Read the Data.
      DWORD dwDownloaded = 0;
      ZeroMemory(pchOutBuffer, dwSize+1);
      if (!WinHttpReadData(hRequest, (LPVOID)pchOutBuffer, dwSize, &dwDownloaded))
      {
        printf("Http read data error.\n");
      }
      else
      {
        // Write buffer to sample binary file
        DWORD wmWritten;
                WriteFile(hFile, pchOutBuffer, dwSize, &wmWritten, NULL);
      }

      delete [] pchOutBuffer;
    }

  } while (dwSize>0);

  printf("Done\n");

11. Some housekeeping works before we exit the application. Make sure that we free all the handles.

1
2
3
4
5
  // Housekeeping
  CloseHandle(hFile);
  WinHttpCloseHandle(hRequest);
  WinHttpCloseHandle(hConnected);
  WinHttpCloseHandle(hInternet);

5. Compile and run you code in command windows now and you should see the following screenshot. VC++ File Download Example

Download source code: FileDownloadSample.zip