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