项目目的:根据从客户端发送到服务器的请求发送的消息 ID 下载特定文件。文件将在服务器上创建并传输到客户端。

在这里,我没有共享整个代码,但显示了必要的内容,目的是演示迁移所需的更改。

进行更改。我参考了现有的 afxisapi.h,afxisapi.inl 和 HttpExt.h,它们随 VS2005 一起提供。

  • 使用 EXTENSION_CONTROL_BLOCK 而不是 CHttpServerContext。EXTENSION_CONTROL_BLOCK 是 IIS 和 ISAPI 扩展用于交换信息的主要结构。它包含有关新请求的所有信息。

  • 从 MFC 扩展类中删除 CHttpServer 类的依赖项。如果在项目中使用它,请删除 http 命令解析消息映射。在 VS2005 之后,正在删除像 ON_PARSE_COMMAND,BEGIN_PARSE_MAP,END_PARSE_MAP 和 DEFAULT_PARSE_COMMAND 这样的宏。

  • 在你之前从 CHttpSever 类派生的 MFC 扩展类中实现你自己的 GetExtensionVersion,TerminateExtension 和 HttpExtensionProc 函数。这些功能

  • GetExtensionVersion()GetExtensionVersion 函数是 IIS 中的第一个入口点函数。此功能允许你的 ISAPI 扩展通过 IIS 注册其版本信息。

BOOL  CISAPIExtension::GetExtensionVersion( HSE_VERSION_INFO* pVer )
{
    ISAPIVERIFY(
       ::LoadString( AfxGetResourceHandle(),
                          IDS_SERVER,
                          sz,
                          HSE_MAX_EXT_DLL_NAME_LEN) );

       _tcscpy_s( pVer->lpszExtensionDesc, ( strlen( sz ) + 1U ), sz )
}
  • HttpExtensionProc():HttpExtensionProc 函数是 IIS 调用的 ISAPI 扩展的主入口点。它公开了 IIS 用于访问扩展程序公开的功能的方法。从扩展控制块中提取请求信息并进行处理。
DWORD CISAPIExtension::HttpExtensionProc(LPEXTENSION_CONTROL_BLOCK pECB)
{
try
{
    if (strcmp(pECB->lpszMethod, "POST") == 0)
    {
        if (0 < pECB->cbTotalBytes)
        {
            unsigned long ulSize = pECB->cbTotalBytes;
            char* lpszContent = new char[ulSize + 1];
            if (NULL != lpszContent)
            {
                memcpy(lpszContent, pECB->lpbData, ulSize);
                lpszContent[ulSize] = '\0';
                
                std::string message_id;
                // Extract Message id from lpszContent using string operation.

                if(strcmp(pECB->lpszQueryString, "DownloadFile") == 0)
                {            
                    DownloadFileFunction(pECB, message_id));            
                }
                
                delete[] lpszContent;
                lpszContent = NULL;
            }
        }
    }
}    
catch (...)
{

}
return HSE_STATUS_SUCCESS;
}
  • 使用 EXTENSION_CONTROL_BLOCK 的 ServerSupportFunction 而不是 CHttepServerContext 的 TransmitFile 函数。以前,TransmitFile() 用于文件传输。
  • 在 ServerSupportFunction 中使用 HSE_REQ_TRANSMIT_FILE 进行文件传输。
  • 在 HSE_TF_INFO 结构中拉出传输文件信息。
  • 创建一个将在异步 I / O 完成时调用的回调函数(AsyncIOCompletionFunction)。
void WINAPI  AsyncIOCompletionFunction(
EXTENSION_CONTROL_BLOCK * pECB,
PVOID    pContext,
DWORD    cbIO,
DWORD    dwError)
{
    HSE_CUSTOM_ERROR_INFO* pErrorInfo = (HSE_CUSTOM_ERROR_INFO*)pContext;
    DWORD dwIOStatus = dwError == NO_ERROR ?
        HSE_STATUS_SUCCESS :
        HSE_STATUS_ERROR;

    if (NULL != pErrorInfo)
    {
        //
        // log HTTP status code
        //
        pECB->dwHttpStatusCode = atoi(pErrorInfo->pszStatus);

        delete pErrorInfo;
        pErrorInfo = NULL;
    }

    pECB->ServerSupportFunction(
        pECB->ConnID,
        HSE_REQ_DONE_WITH_SESSION,
        &dwIOStatus,
        (LPDWORD)NULL,
        (LPDWORD)NULL);
}

DownloadFileFunction() 的代码片段

HSE_TF_INFO pHSEInfo;

pHSEInfo.hFile            = hFile;
pHSEInfo.dwFlags          = HSE_IO_ASYNC;
pHSEInfo.pHead            = (PVOID) pvHeader;
pHSEInfo.HeadLength       = dwHeaderLen;
pHSEInfo.pContext         = 0;
pHSEInfo.pTail            = 0;
pHSEInfo.TailLength       = 0;
pHSEInfo.BytesToWrite     = 0;
pHSEInfo.Offset           = 0;
pHSEInfo.pfnHseIO         = AsyncIOCompletionFunction; // callback function that will     be called on asynchronous I/O completion
pHSEInfo.pszStatusCode    = LPCSTR("200 OK");

bResult = m_pCtxt->ServerSupportFunction(m_pCtxt->ConnID, HSE_REQ_TRANSMIT_FILE, &pHSEInfo, 0, 0);