对于大文件偏移量,他们是否有 HSE_REQ_TRANSMIT_FILE 的替代方案?
Is their any alternative of HSE_REQ_TRANSMIT_FILE for large file offset?
我对 HSE_REQ_TRANSMIT_FILE 所需的 HSE_TF_INFO 结构成员 Offset 有疑问。
让我解释一下我的问题:
我有一个 ISAPI 扩展(32 位),可以将图像发回 Web 客户端(JPEG 小于 100 KB)。由于这些图像数量众多(超过 500 万),我创建了一种文件格式,将所有图像存储(和索引)在一个文件中。当然这个文件大于 32 位偏移量的 4GBytes 限制。
所以关于请求,我的 ISAPI 扩展在大文件中寻找好的偏移量,读取小图像并将其发送回客户端。
我尝试通过异步发送这些小图像来提高我的 ISAPI 扩展的响应时间,因为它似乎更有效。
所以我尝试了 HSE_REQ_TRANSMIT_FILE 这正是我发送包裹在大文件中的小图像所需要的:
- 一个文件句柄(在大文件上);
- 一个偏移量(小图像的);
- 和(我的小图片的)大小。
但是HSE_TF_INFO::Offset是一个DWORD,所以限制为4 Go!!!!!
所以奇怪的是 ReadFile 函数(从句柄读取)作为 OVERLAPED(似乎是为异步设计的结构 I/O)作为两个 Offset 成员(Offset 和 OffsetHigh)来模拟 64 位偏移等等支持大文件搜索。
有没有支持大文件偏移量的HSE_TF_INFO_EX?或者有没有一种特殊的方法可以使用 HSE_TF_INFO 来查找超过 4GB 的文件?
感谢您的帮助...
您可以使用HSE_REQ_VECTOR_SEND
- this is more general than HSE_REQ_TRANSMIT_FILE
. how you can view HSE_REQ_VECTOR_SEND
let send any numbers of HSE_VECTOR_ELEMENT
structures. how we can view HSE_VECTOR_ELEMENT
让发送文件或内存缓冲区。如果是文件 - cbOffset
(文件中的偏移量)和 cbSize
(来自 cbOffset 的文件数据的字节数) - 两者都是 ULONGLONG
- 因此不受大小限制
演示(纯粹为了清楚起见)我们如何转换HSE_REQ_VECTOR_SEND
to more general HSE_REQ_VECTOR_SEND
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 位大小和偏移量,通常需要下一个代码:
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_SEND
and HSE_REQ_TRANSMIT_FILE
internal call HttpSendResponseEntityBody
我对 HSE_REQ_TRANSMIT_FILE 所需的 HSE_TF_INFO 结构成员 Offset 有疑问。
让我解释一下我的问题:
我有一个 ISAPI 扩展(32 位),可以将图像发回 Web 客户端(JPEG 小于 100 KB)。由于这些图像数量众多(超过 500 万),我创建了一种文件格式,将所有图像存储(和索引)在一个文件中。当然这个文件大于 32 位偏移量的 4GBytes 限制。
所以关于请求,我的 ISAPI 扩展在大文件中寻找好的偏移量,读取小图像并将其发送回客户端。 我尝试通过异步发送这些小图像来提高我的 ISAPI 扩展的响应时间,因为它似乎更有效。
所以我尝试了 HSE_REQ_TRANSMIT_FILE 这正是我发送包裹在大文件中的小图像所需要的:
- 一个文件句柄(在大文件上);
- 一个偏移量(小图像的);
- 和(我的小图片的)大小。
但是HSE_TF_INFO::Offset是一个DWORD,所以限制为4 Go!!!!! 所以奇怪的是 ReadFile 函数(从句柄读取)作为 OVERLAPED(似乎是为异步设计的结构 I/O)作为两个 Offset 成员(Offset 和 OffsetHigh)来模拟 64 位偏移等等支持大文件搜索。
有没有支持大文件偏移量的HSE_TF_INFO_EX?或者有没有一种特殊的方法可以使用 HSE_TF_INFO 来查找超过 4GB 的文件?
感谢您的帮助...
您可以使用HSE_REQ_VECTOR_SEND
- this is more general than HSE_REQ_TRANSMIT_FILE
. how you can view HSE_REQ_VECTOR_SEND
let send any numbers of HSE_VECTOR_ELEMENT
structures. how we can view HSE_VECTOR_ELEMENT
让发送文件或内存缓冲区。如果是文件 - cbOffset
(文件中的偏移量)和 cbSize
(来自 cbOffset 的文件数据的字节数) - 两者都是 ULONGLONG
- 因此不受大小限制
演示(纯粹为了清楚起见)我们如何转换HSE_REQ_VECTOR_SEND
to more general HSE_REQ_VECTOR_SEND
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 位大小和偏移量,通常需要下一个代码:
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_SEND
and HSE_REQ_TRANSMIT_FILE
internal call HttpSendResponseEntityBody