專案目的:根據從客戶端傳送到伺服器的請求傳送的訊息 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);