Winapi 对于大文件偏移量,他们是否有HSE要求传输文件的替代方案?

Winapi 对于大文件偏移量,他们是否有HSE要求传输文件的替代方案?,winapi,iis,iis-7.5,iis-8,isapi,Winapi,Iis,Iis 7.5,Iis 8,Isapi,我对HSE请求传输文件所需的HSE TF INFO结构成员偏移量有问题 让我解释一下我的问题: 我有一个ISAPI扩展(32位),可以将图像发送回web客户端(JPEG小于100KB)。由于这些图像数量很大(超过500万),我创建了一种文件格式,将所有图像存储(并索引)在一个文件中。当然,该文件大于32位偏移量的4GBytes限制 因此,对于这个请求,我的ISAPI扩展在大文件中寻找合适的偏移量,读取小图像并将其发送回客户端。 我尝试通过异步发送这些小图像来提高ISAPI扩展的响应时间,因为这似

我对HSE请求传输文件所需的HSE TF INFO结构成员偏移量有问题

让我解释一下我的问题:

我有一个ISAPI扩展(32位),可以将图像发送回web客户端(JPEG小于100KB)。由于这些图像数量很大(超过500万),我创建了一种文件格式,将所有图像存储(并索引)在一个文件中。当然,该文件大于32位偏移量的4GBytes限制

因此,对于这个请求,我的ISAPI扩展在大文件中寻找合适的偏移量,读取小图像并将其发送回客户端。 我尝试通过异步发送这些小图像来提高ISAPI扩展的响应时间,因为这似乎更有效

因此,我尝试了HSE_REQ_TRANSMIT_文件,这正是我发送大文件中包裹的小图像所需要的:

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

    是否有一种HSE_TF_INFO_EX可以支持大文件偏移?或者,是否有一种特殊的方法可以使用HSE_TF_信息来查找超过4G字节的文件

    感谢您的帮助…

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

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

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

    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;
    }
    
    struct传输文件\u上下文
    {
    乌龙龙(ULONGLONG)BytesToWrite ;;
    乌龙龙(ULONGLONG);;
    句柄文件;
    char_szHeaders[];
    传输文件上下文(HANDLE hFile、ULONGLONG BytesToWrite、ULONGLONG cbOffset);
    ~TRANSMIT_FILE_CONTEXT();
    void*运算符新(大小\u t cb、ULONG CBHeader)
    {
    return::运算符new(cb+cbHeaders);
    }
    void运算符删除(void*p)
    {
    ::运算符删除(p);
    }
    静态无效WINAPI已完成(
    lpECB扩展控制块lpECB,
    PVOID pContext,
    DWORD/*cbIO*/,,
    德沃德误差
    )
    {
    DbgPrint(“完成(%p,%u)\n),lpECB->ConnID,dwError);
    dwError=(dwError==NOERROR?HSE_状态_成功:HSE_状态_错误);
    lpECB->ServerSupportFunction(lpECB->ConnID,HSE_REQ_DONE_与_SESSION,&dwError,0,0);
    删除reinterpret_cast(pContext);
    }
    DWORD发送(lpECB扩展\控制\块lpECB)
    {
    if(lpECB->ServerSupportFunction(lpECB->ConnID,HSE需求IO完成,OnIoComplete,0,(DWORD*)此))
    {
    HSE_向量_元素[2]={
    {HSE_向量_元素_类型_内存_缓冲区,_szHeaders,0,strlen(_szHeaders)},
    {HSE\u向量\u元素\u类型\u文件\u句柄,\u hFile,\u cbOffset,\u BytesToWrite}
    };
    HSE_响应_向量rv={
    HSE|IO|U异步| HSE|IO|U发送后断开| HSE|IO|U最终发送|,
    0,
    0,
    (元件)的RTL\u编号,
    元素
    };
    if(lpECB->ServerSupportFunction(lpECB->ConnID,HSE\U REQ\U VECTOR\U SEND,&rv,0,0))
    {
    返回HSE_状态_待定;
    }
    }
    删除此项;
    返回HSE_状态_错误;
    }
    };
    DWORD WINAPI HttpExtensionProc(LPEXTENSION\u CONTROL\u BLOCK lpECB)
    {
    //...
    如果(传输文件上下文*p=new(cb+1)传输文件上下文(*)
    {
    //...
    返回p->发送(lpECB);
    }
    //...
    返回HSE_状态_错误;
    }
    

    还要注意的是,无论是内部通话还是内部通话,都是的,不幸的是,7年后forums.iis.net上没有回复:(可能是因为你不在这个论坛;)@RbMn我很高兴你在这里,我没有想到HSE需求向量发送。我让这个问题多开放几天,让我有时间来实施和验证它it@loki-
    HSE\u-REQ\u-TRANSMIT\u文件
    HSE\u-REQ\u-VECTOR\u-SEND
    的特例。我昨天在self-ISAPI扩展中检查了这个-完美工作。首先,我认为这两个请求映射到
    TransmitFile
    TransmitPackets
    ,但在调试代码时,查看这两个
    HSE\u REQ\uu
    上的请求是否真正调用了相同的
    httpsendsresponseentitybody
    。在HTTP\u DATA\u CHUNK中我们的数据。对于文件块-在
    HTTP_BYTE_RANGE
    ]()结构中-其中
    StartingOffset
    Length
    两者都
    ULARGE_INTEGER
    我相信您在这里遗漏了一些重要的内容-清理传入的hFile句柄。使用标志中指定的HSE_IO_ASYNC调用vector send时,实际上,您需要将句柄的所有权移交给TRANSMIT_FILE_上下文结构-使其负责在完成或结构的析构函数时关闭句柄-否则您将泄漏文件句柄。@CWoods-close FILE HANDLE位于
    ~TRANSMIT_FILE_CONTEXT()中-在操作完成时调用。但是如果
    Send
    失败(比如说因为
    HSE\u REQ\u VECTOR\u Send
    fail),我的代码片段中没有显示析构函数的代码-我只是调用
    删除这个
    (所以析构函数被调用),然后在这里关闭文件和其他资源清理并返回
    HSE\u STATUS\u ERROR
    。否则我返回
    HSE\u STATUS\u PENDING
    。当
    Se
    
    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;
    }