可以使用 WinInet 添加 FTP 支持,以便从应用程序中下载和上传文件。 可以重写 OnStatusCallback ,并使用 dwContext 参数在搜索和下载文件时向用户提供进度信息。
本文包含以下主题:
下面的代码摘录演示了如何创建简单的浏览器、下载网页、FTP 文件以及搜索 gopher 文件。 它们不是完整的示例,并非所有示例都包含异常处理。
有关 WinInet 的其他信息,请参阅 Win32 Internet 扩展(WinInet)。
创建非常简单的浏览器
#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();
}
下载网页
//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 文件
#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();
}
检索 Gopher 目录
#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();
}
使用 OnStatusCallback
使用 WinInet 类时,可以使用应用程序的 CInternetSession 对象的 OnStatusCallback 成员来检索状态信息。 如果派生自己的 CInternetSession
对象、替代 OnStatusCallback
和启用状态回调,MFC 将调用函数 OnStatusCallback
,其中包含有关该 Internet 会话中所有活动的进度信息。
由于单个会话可能支持多个连接(这些连接在其生存期内可能执行许多不同的作), OnStatusCallback
因此需要一种机制来识别具有特定连接或事务的每个状态更改。 该机制由提供给 WinInet 支持类中许多成员函数的上下文 ID 参数提供。 此参数始终为 DWORD 类型,并且始终命名为 dwContext。
分配给特定 Internet 对象的上下文仅用于标识对象在对象成员CInternetSession
中OnStatusCallback
引发的活动。 调用接收 OnStatusCallback
多个参数;这些参数协同工作,告知应用程序已针对哪个事务和连接进行了哪些进度。
创建 CInternetSession
对象时,可以向构造函数指定 dwContext 参数。
CInternetSession
本身不使用上下文 ID;而是将上下文 ID 传递给任何未显式获取其自己的上下文 ID 的 InternetConnection 派生对象。 反过来,如果不显式指定不同的上下文 ID,这些 CInternetConnection
对象会将上下文 ID 传递给 CInternetFile
它们创建的对象。 另一方面,如果指定自己的特定上下文 ID,该对象及其执行的任何工作都将与该上下文 ID 相关联。 可以使用上下文 ID 来确定函数中 OnStatusCallback
提供的状态信息。
传输文件时显示进度信息
例如,如果编写一个应用程序,该应用程序创建与 FTP 服务器的连接以读取文件,并连接到 HTTP 服务器以获取网页,则你将有一个对象、两个CInternetSession
对象(一个是一个CFtpSession
对象,另一个是一个)和两CInternetFile
个CHttpSession
对象(一个用于每个CInternetConnection
连接)。 如果对 dwContext 参数使用了默认值,则无法区分 OnStatusCallback
指示 FTP 连接的进度的调用和指示 HTTP 连接的进度的调用。 如果指定 dwContext ID(稍后可以测试该 OnStatusCallback
ID),你将知道哪个作生成了回调。