WinInet Basics

You can use WinInet to add FTP support to download and upload files from within your application. You can override OnStatusCallback and use the dwContext parameter to provide progress information to users as you search for and download files.

This article contains the following topics:

The code excerpts below demonstrate how to create a simple browser, download a Web page, FTP a file, and search for a gopher file. They are not meant as complete examples and not all contain exception handling.

For additional information on WinInet, see Win32 Internet Extensions (WinInet).

Create a Very Simple Browser

#include <afxinet.h>

void DisplayPage(LPCTSTR pszURL)
{
   CInternetSession session(_T("My Session"));
   CStdioFile *pFile = NULL;
   CHAR szBuff[1024];
   //use a URL and print a Web page to the console
   pFile = session.OpenURL(pszURL);
   while (pFile->Read(szBuff, 1024) > 0)
   {
      printf_s("%1023s", szBuff);
   }
   delete pFile;
   session.Close();
}

Download a Web Page

//this code excerpt also demonstrates try/catch exception handling
#include <afxinet.h>

void DisplayHttpPage(LPCTSTR pszServerName, LPCTSTR pszFileName)
{
   CInternetSession session(_T("My Session"));
   CHttpConnection *pServer = NULL;
   CHttpFile *pFile = NULL;
   try
   {
      CString strServerName;
      INTERNET_PORT nPort = 80;
      DWORD dwRet = 0;

      pServer = session.GetHttpConnection(pszServerName, nPort);
      pFile = pServer->OpenRequest(CHttpConnection::HTTP_VERB_GET, pszFileName);
      pFile->SendRequest();
      pFile->QueryInfoStatusCode(dwRet);

      if (dwRet == HTTP_STATUS_OK)
      {
         CHAR szBuff[1024];
         while (pFile->Read(szBuff, 1024) > 0)
         {
            printf_s("%1023s", szBuff);
         }
      }
      delete pFile;
      delete pServer;
   }
   catch (CInternetException *pEx)
   {
      //catch errors from WinInet
      TCHAR pszError[64];
      pEx->GetErrorMessage(pszError, 64);
      _tprintf_s(_T("%63s"), pszError);
   }
   session.Close();
}

FTP a File

#include <afxinet.h>

void GetFtpFile(LPCTSTR pszServerName, LPCTSTR pszRemoteFile, LPCTSTR pszLocalFile)
{
   CInternetSession session(_T("My FTP Session"));
   CFtpConnection *pConn = NULL;

   pConn = session.GetFtpConnection(pszServerName);
   //get the file
   if (!pConn->GetFile(pszRemoteFile, pszLocalFile))
   {
      //display an error
   }
   delete pConn;
   session.Close();
}

Retrieve a Gopher Directory

#include <afxinet.h>

void RetrieveGopherFile(LPCTSTR pszGopherSite, LPCTSTR pszFile)
{
   CInternetSession session(_T("My Gopher Session"));
   CGopherConnection *pConn = NULL;
   CGopherFileFind *pFile;

   pConn = session.GetGopherConnection(pszGopherSite);
   pFile = new CGopherFileFind(pConn);
   BOOL bFound = pFile->FindFile(pszFile);
   while (bFound)
   {
      //retrieve attributes of found file
      bFound = pFile->FindNextFile();
   }
   delete pFile;
   delete pConn;
   session.Close();
}

Use OnStatusCallback

When using the WinInet classes, you can use the OnStatusCallback member of your application's CInternetSession object to retrieve status information. If you derive your own CInternetSession object, override OnStatusCallback, and enable status callbacks, MFC will call your OnStatusCallback function with progress information about all the activity in that Internet session.

Because a single session might support several connections (which, over their lifetime, might perform many different distinct operations), OnStatusCallback needs a mechanism to identify each status change with a particular connection or transaction. That mechanism is provided by the context ID parameter given to many of the member functions in the WinInet support classes. This parameter is always of type DWORD and is always named dwContext.

The context assigned to a particular Internet object is used only to identify the activity the object causes in the OnStatusCallback member of the CInternetSession object. The call to OnStatusCallback receives several parameters; these parameters work together to tell your application what progress has been made for which transaction and connection.

When you create a CInternetSession object, you can specify a dwContext parameter to the constructor. CInternetSession itself doesn't use the context ID; instead, it passes the context ID on to any InternetConnection-derived objects that don't explicitly get a context ID of their own. In turn, those CInternetConnection objects will pass the context ID along to CInternetFile objects they create if you don't explicitly specify a different context ID. If, on the other hand, you do specify a specific context ID of your own, the object and any work it does will be associated with that context ID. You can use the context IDs to identify what status information is being given to you in your OnStatusCallback function.

Display Progress Information While Transferring Files

For example, if you write an application that creates a connection with an FTP server to read a file and also connects to an HTTP server to get a Web page, you'll have a CInternetSession object, two CInternetConnection objects (one would be a CFtpSession and the other would be a CHttpSession), and two CInternetFile objects (one for each connection). If you used default values for the dwContext parameters, you would not be able to distinguish between the OnStatusCallback invocations that indicate progress for the FTP connection and the invocations that indicate progress for the HTTP connection. If you specify a dwContext ID, which you can later test for in OnStatusCallback, you will know which operation generated the callback.

See also

MFC Internet Programming Basics
Win32 Internet Extensions (WinInet)