首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >他们是否可以选择HSE_REQ_TRANSMIT_FILE作为大文件偏移量?

他们是否可以选择HSE_REQ_TRANSMIT_FILE作为大文件偏移量?
EN

Stack Overflow用户
提问于 2018-01-27 06:38:42
回答 1查看 154关注 0票数 0

我对HSE_TF_INFO结构成员偏移量有问题,这是HSE_REQ_TRANSMIT_FILE所需要的。

让我解释一下我的问题:

我有一个ISAPI扩展(32位),将图像发送回web客户端(JPEG小于100 KBytes)。由于有大量这些图像(超过500万),我创建了一个文件格式,将所有图像存储在一个文件中(和indexe)。当然,这个文件比32位偏移的4GBytes限制要大。

因此,对于请求,我的ISAPI扩展在大文件中寻找好的偏移量,读取小图像并将其发送回客户端。我试图通过异步发送这个小映像来改善ISAPI扩展的响应时间,因为它看起来更有效。

因此,我尝试使用HSE_REQ_TRANSMIT_FILE来发送封装在大文件中的小图像,这正是我所需要的:

  1. 文件句柄(在大文件上);
  2. (小图像的)偏移;
  3. 和(我的小照片)的大小。

但是HSE_TF_INFO::Offset是一个DWORD,所以限制在4上!因此,奇怪的是,ReadFile函数(从句柄中读取)作为OVERLAPED (似乎是为异步I/O设计的结构),作为两个偏移成员(偏移量和OffsetHigh)来模拟64位偏移量,从而支持大文件查找。

是否有一种可以支持大文件偏移量的HSE_TF_INFO_EX?或者,是否有一种特殊的方法可以使用HSE_TF_INFO在超过4G的文件中查找?

谢谢你的帮助..。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-02-18 21:02:43

您可以使用HSE_REQ_VECTOR_SEND --这比HSE_REQ_TRANSMIT_FILE更通用。如何查看HSE_REQ_VECTOR_SEND让发送任意数量的HSE_VECTOR_ELEMENT结构。如何查看HSE_VECTOR_ELEMENT,让发送文件或内存缓冲区。如果文件-- cbOffset (偏移到文件中)和cbSize (来自cbOffset的文件数据的字节数)--两者都是ULONGLONG --因此不受大小限制。

演示(纯粹是为了清晰起见)如何将HSE_REQ_VECTOR_SEND转换为更通用的HSE_REQ_VECTOR_SEND

代码语言:javascript
运行
复制
BOOL Repack(LPEXTENSION_CONTROL_BLOCK lpECB, LPHSE_TF_INFO ti)
{
    // code have same effect as call 
    // lpECB->ServerSupportFunction(lpECB->ConnID, HSE_REQ_TRANSMIT_FILE, ti, 0, 0);

    if (lpECB->ServerSupportFunction(lpECB->ConnID, HSE_REQ_IO_COMPLETION, ti->pfnHseIO, 0, (DWORD*)ti->pContext))
    {
        HSE_VECTOR_ELEMENT Element[3] = {
            { HSE_VECTOR_ELEMENT_TYPE_MEMORY_BUFFER, ti->pHead, 0, ti->HeadLength },
            { HSE_VECTOR_ELEMENT_TYPE_FILE_HANDLE, ti->hFile, ti->Offset, ti->BytesToWrite },
            { HSE_VECTOR_ELEMENT_TYPE_MEMORY_BUFFER, ti->pTail, 0, ti->TailLength }
        };

        HSE_RESPONSE_VECTOR rv = {
            HSE_IO_ASYNC|HSE_IO_DISCONNECT_AFTER_SEND|HSE_IO_FINAL_SEND,
            0,
            0,
            RTL_NUMBER_OF(Element),
            Element
        };

        if (!Element[2].cbSize) rv.nElementCount--;

        if (!Element[0].cbSize) rv.lpElementArray++, rv.nElementCount--;

        if (lpECB->ServerSupportFunction(lpECB->ConnID, HSE_REQ_VECTOR_SEND, &rv, 0, 0))
        {
            return TRUE;
        }
    }

    return FALSE;
}

因此,如果需要完整的64位大小和偏移量,通常需要下一段代码:

代码语言:javascript
运行
复制
struct TRANSMIT_FILE_CONTEXT 
{
    ULONGLONG _BytesToWrite;
    ULONGLONG _cbOffset;
    HANDLE _hFile;
    char _szHeaders[];

    TRANSMIT_FILE_CONTEXT(HANDLE hFile, ULONGLONG BytesToWrite, ULONGLONG _cbOffset);

    ~TRANSMIT_FILE_CONTEXT();

    void* operator new(size_t cb, ULONG cbHeaders)
    {
        return ::operator new(cb + cbHeaders);
    }

    void operator delete(void* p)
    {
        ::operator delete(p);
    }

    static VOID WINAPI OnIoComplete (
        LPEXTENSION_CONTROL_BLOCK lpECB,
        PVOID pContext,
        DWORD /*cbIO*/,
        DWORD dwError
        )
    {
        DbgPrint("OnIoComplete(%p, %u)\n", lpECB->ConnID, dwError);

        dwError = (dwError == NOERROR ? HSE_STATUS_SUCCESS : HSE_STATUS_ERROR);

        lpECB->ServerSupportFunction(lpECB->ConnID, HSE_REQ_DONE_WITH_SESSION, &dwError, 0, 0);

        delete reinterpret_cast<TRANSMIT_FILE_CONTEXT*>(pContext);
    }

    DWORD Send(LPEXTENSION_CONTROL_BLOCK lpECB)
    {
        if (lpECB->ServerSupportFunction(lpECB->ConnID, HSE_REQ_IO_COMPLETION, OnIoComplete, 0, (DWORD*)this))
        {
            HSE_VECTOR_ELEMENT Element[2] = {
                { HSE_VECTOR_ELEMENT_TYPE_MEMORY_BUFFER, _szHeaders, 0, strlen(_szHeaders) },
                { HSE_VECTOR_ELEMENT_TYPE_FILE_HANDLE, _hFile, _cbOffset, _BytesToWrite }
            };

            HSE_RESPONSE_VECTOR rv = {
                HSE_IO_ASYNC|HSE_IO_DISCONNECT_AFTER_SEND|HSE_IO_FINAL_SEND,
                0,
                0,
                RTL_NUMBER_OF(Element),
                Element
            };

            if (lpECB->ServerSupportFunction(lpECB->ConnID, HSE_REQ_VECTOR_SEND, &rv, 0, 0))
            {
                return HSE_STATUS_PENDING;
            }
        }

        delete this;

        return HSE_STATUS_ERROR;
    }
};

DWORD WINAPI HttpExtensionProc(LPEXTENSION_CONTROL_BLOCK lpECB)
{
  //...
                if (TRANSMIT_FILE_CONTEXT* p = new(cb + 1) TRANSMIT_FILE_CONTEXT(*))
                {
                    //...

                    return p->Send(lpECB);
                }
    //...

    return HSE_STATUS_ERROR;
}

还请注意,HSE_REQ_VECTOR_SENDHSE_REQ_TRANSMIT_FILE内部调用HttpSendResponseEntityBody

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/48473310

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档