实现文件上传的问题 我接收到表单中<input type=file name=upfile>中的值为 c:\test.zip请问isapi 怎么实现上传?能否给出源代码? 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 转:利用ISAPI开发CGI程序闻怡洋 http://www.vchelp.net/--------------------------------------------------------------------------------ISAPI(Internet Server API)最初是微软为IIS服务器所提供的一种CGI应用开发接口,其主要的目的也是为CGI开发提供好的开发接口,如果不负责的讲ISAPI也可以认为是类似WinCGI的一种开发模式,只不过ISAPI通过映射宏来取得用户表单传送的参数。这一点上和MFC消息映射宏很相似。当然ISAPI的推出同时还具备了很多其他的特性:ISAPI以DLL动态连接库的方式实现,所以加载较普通的EXE运行程序快,而且系统不会在使用完后马上清除掉DLL在内存中的空间,所以再次使用时会获得更快的速度。ISAPI在调用者的内部以线程方式运行,所以和CGI进程相比较需要的运行空间也更小。在同一个DLL中可以集中多个处理函数,并且通过映射宏来指明不同的函数分别对什么样的请求来进行处理。由于与IIS的集成,所以可以利用ISAPI开发ISAPI过滤器。通过过滤器可以完成例如用户权限检测,数据加密,压缩,日志等功能,IIS服务器的功能也可以通过ISAPI过滤器来得到增强。到目前为止,很多非M$的WEB服务器也都添加了对ISAPI的支持。在同一个DLL中可以集中多个处理函数,所以执行ISAPI的请求和执行普通CGI的请求有一点区别,在URL中需要填写如下形式http://.../cgi-bin/test.dll?function_name&name=xxx&email=yyy,function_name表示的就是功能名称,为了能够正确处理你必须将其映射到DLL中的一个处理函数上。对与未映射的功能都将由一个默认函数处理。VC4.2以上版本为创建一个ISAPI程序提供了向导程序,在新建工程时选择ISAPI Extension Wizard并在以后的对话框中选择创建服务器扩展和输入相关的信息就可以了。一个最简单的ISAPI程序至少包含了一个由CHttpServer类所派生的新类,并且在该类中进行了基本的映射,重载了BOOL GetExtensionVersion(HSE_VERSION_INFO* pVer)函数和提供了形式如void Default(CHttpServerContext* pCtxt)的成员函数。幸运的是向导程序已经为我们做好了这一切并创建了最基本的代码。Default函数用于处理没有带参数首先我们修改Default函数中的代码,首先我们该写其中的相关代码成为如下:void CTestisaExtension::Default(CHttpServerContext* pCtxt){ //Print the <HTML> <BODY> tags. StartContent(pCtxt); //Print the title. WriteTitle(pCtxt); *pCtxt << _T("<p>演示</p>"); *pCtxt << _T("<p>目前是Default成员函数其作用</p>"); //Print </HTML> </BODY> tags. EndContent(pCtxt);}然后用以下方式调用:http://.../cgi-bin/test.dll?Default或http://.../cgi-bin/test.dll?。你就会看到输出的HTML页面了。<FORM ACTION="test.dll?Add" METHOD=POST><INPUT NAME="name"><INPUT NAME="id"><INPUT TYPE=SUBMIT></FORM>上面表单要求用户输入了用户名和ID号,所以传送的数据形式形式应该如同:http://.../test.dll?Add&name=xxx&id=yyy,我们可以通过处理命令映射宏来指明处理命令的函数,然后通过参数映射宏对数据进行分解,分解后的数据将会存放入指定的变量。使用方法为:ON_PARSE_COMMAND(Add, CTestExtension, ITS_PSTR ITS_I4)ON_PARSE_COMMAND_PARAMS("name id")ON_PARSE_COMMAND宏中需要指明函数名,类名和参数类型列表,ON_PARSE_COMMAND_PARAMS宏中需要根据前一个宏中所列出的参数列表来指明表单中的变量名称列表。最后一步就是定义一个名称与请求URL中?后命令名称相同的成员函数,参数的设置要与ON_PARSE_COMMAND宏中的参数列表定义相符合,在这个例子中为:void CTestExtension::Add(CHttpServerContext* pCtxt,LPTSTR pszName,int iID)。参数类型列表中可以使用下面的类型后面为该类型的说明:ITS_EMPTY 无数据ITS_PSTR 字符串LPCSTRITS_I2 shortITS_I4 longITS_R4 floatITS_R8 double下面我们看一个更复杂的表单,表单定义如下:<FORM ACTION="test.dll?Delete" METHOD=POST><INPUT NAME="name"><INPUT NAME="month"><SELECT NAME="mode"> <OPTION VALUE=1>All <OPTION VALUE=2>Before <OPTION VALUE=3>After<INPUT TYPE=HIDDEN NAME=pwd VALUE=xxx><INPUT TYPE=SUBMIT></FORM>定义映射和处理函数如下:ON_PARSE_COMMAND(Add, CTestExtension, ITS_PSTR ITS_I4 ITS_I4 ITS_PSTR)ON_PARSE_COMMAND_PARAMS("name month mode pwd")void CTestExtension::Add(CHttpServerContext* pCtxt,LPTSTR pszName,int iMonth,int iMode,LPTSTR pszPwd)。ISAPI程序的输出:在所有的命令处理函数中第一个参数都是CHttpServerContext*指针,我们所有的输出都要通过它进行,在CHttpServerContext类中定义了<<操作符,通过该操作符我们可以方便的输出字符串,数字,二进制数据。输出的方法为:*pCtxt<<"this is a string";*pCtxt<<'c';*pCtxt<<10;可以看得出输出是很简单的,一个完整的输出过程应该是如同下面的形式: StartContent(pCtxt);//开始输出 WriteTitle(pCtxt);//输出头部信息,相当于输出<TITLE> *pCtxt << "your string"; EndContent(pCtxt);//结束输出我们所使用的ISAPI扩展类是由CHttpServer所派生,可以调用CHttpServer::AddHeader来指明返回数据的类型,例如下面的代码演示了输出纯文本:void CTestisaExtension::Default(CHttpServerContext* pCtxt){ AddHeader(pCtxt, "Content-type = text/plain\r\n"); (*pCtxt) << "Hello world!\r\n";}我们可以重载某些函数来达到加强控制的目的,可重载的函数有以下这些:virtual LPCTSTR CHttpServer::GetTitle( ) const;返回<TITLE>部分信息virtual BOOL CHttpServer::OnParseError( CHttpServerContext* pCtxt, int nCause );错误处理virtual void CHttpServer::StartContent( CHttpServerContext* pCtxt ) const;输出<HTML><BODY>部分信息virtual void CHttpServer::EndContent( CHttpServerContext* pCtxt ) const;输出</BODY></HTML>部分信息virtual void CHttpServer::WriteTitle( CHttpServerContext* pCtxt ) const;输出<TITLE></TITLE>部分信息此外我们可以在命令处理函数中利用CHttpServerContext指针来得到CGI中的相关环境变量,在CHttpServerContext中有一个成员变量m_pECB为下面的结构指针。typedef struct _EXTENSION_CONTROL_BLOCK { DWORD cbSize; //IN 该结构长度 DWORD dwVersion //IN 版本 HCONN ConnID; //IN 连接上下文 DWORD dwHttpStatusCode; //OUT 状态码 CHAR lpszLogData[HSE_LOG_BUFFER_LEN]; //OUT LPSTR lpszMethod; //IN 环境变量REQUEST_METHOD LPSTR lpszQueryString; //IN QUERY_STRING LPSTR lpszPathInfo; //IN PATH_INFO LPSTR lpszPathTranslated; //IN PATH_TRANSLATED DWORD cbTotalBytes; //IN CONTENT_LENGTH DWORD cbAvailable; //IN LPBYTE lpbData; //IN LPSTR lpszContentType; //IN CONTENT_TYPE...其他信息在此忽略} EXTENSION_CONTROL_BLOCK, *LPEXTENSION_CONTROL_BLOCK; 文件长度和内容不可以通过文件操作完成吗?ftell(fhandle);fread(); 不同DLL中,分配和释放内存空间的问题。 全局钩子的nCode和wParam始终为0 哪里错了? 算法达人帮下忙 说说下列算法的中心思想 自已弄了个对话框,如何让它打开时,光标默认落在某Edit控件上? 类似winzip,winrar等压缩软件属于哪个层面的问题,需要开发这样的程序要用语言? 2个问题,DLGPRINT的 c语言中的组合快捷键(如选择,复制,剪切,粘贴)都有哪些,恳请高手相告? 全局变量在什么地方定义 控制RS485通信,好难!!! 我想问问各位高手,怎样提高自己的设计和分析能力 关于ATL响应事件的问题!务必请高手帮忙!!! 两个对话框类如何通信?
利用ISAPI开发CGI程序
闻怡洋 http://www.vchelp.net/
----------------------------------------------------------------------------
----
ISAPI(Internet Server API)最初是微软为IIS服务器所提供的一种CGI应用开发接口
,其主要的目的也是为CGI开发提供好的开发接口,如果不负责的讲ISAPI也可以认为是
类似WinCGI的一种开发模式,只不过ISAPI通过映射宏来取得用户表单传送的参数。这一
点上和MFC消息映射宏很相似。
当然ISAPI的推出同时还具备了很多其他的特性:
ISAPI以DLL动态连接库的方式实现,所以加载较普通的EXE运行程序快,而且系统不会在
使用完后马上清除掉DLL在内存中的空间,所以再次使用时会获得更快的速度。
ISAPI在调用者的内部以线程方式运行,所以和CGI进程相比较需要的运行空间也更小。在同一个DLL中可以集中多个处理函数,并且通过映射宏来指明不同的函数分别对什么样
的请求来进行处理。
由于与IIS的集成,所以可以利用ISAPI开发ISAPI过滤器。通过过滤器可以完成例如用户
权限检测,数据加密,压缩,日志等功能,IIS服务器的功能也可以通过ISAPI过滤器来
得到增强。
到目前为止,很多非M$的WEB服务器也都添加了对ISAPI的支持。
在同一个DLL中可以集中多个处理函数,所以执行ISAPI的请求和执行普通CGI的请求有一
点区别,在URL中需要填写如下形式http://.../cgi-bin/test.dll?function_name&nam
e=xxx&email=yyy,function_name表示的就是功能名称,为了能够正确处理你必须将其
映射到DLL中的一个处理函数上。对与未映射的功能都将由一个默认函数处理。
VC4.2以上版本为创建一个ISAPI程序提供了向导程序,在新建工程时选择ISAPI Extens
ion Wizard并在以后的对话框中选择创建服务器扩展和输入相关的信息就可以了。
一个最简单的ISAPI程序至少包含了一个由CHttpServer类所派生的新类,并且在该类中
进行了基本的映射,重载了BOOL GetExtensionVersion(HSE_VERSION_INFO* pVer)函数
和提供了形式如void Default(CHttpServerContext* pCtxt)的成员函数。幸运的是向导
程序已经为我们做好了这一切并创建了最基本的代码。
Default函数用于处理没有带参数首先我们修改Default函数中的代码,首先我们该写其
中的相关代码成为如下:
void CTestisaExtension::Default(CHttpServerContext* pCtxt)
{
//Print the <HTML> <BODY> tags.
StartContent(pCtxt);
//Print the title.
WriteTitle(pCtxt);
*pCtxt << _T("<p>演示</p>");
*pCtxt << _T("<p>目前是Default成员函数其作用</p>");
//Print </HTML> </BODY> tags.
EndContent(pCtxt);
}
然后用以下方式调用:http://.../cgi-bin/test.dll?Default或http://.../cgi-bin/
test.dll?。你就会看到输出的HTML页面了。
<FORM ACTION="test.dll?Add" METHOD=POST>
<INPUT NAME="name">
<INPUT NAME="id">
<INPUT TYPE=SUBMIT>
</FORM>
上面表单要求用户输入了用户名和ID号,所以传送的数据形式形式应该如同:http://.
../test.dll?Add&name=xxx&id=yyy,我们可以通过处理命令映射宏来指明处理命令的函
数,然后通过参数映射宏对数据进行分解,分解后的数据将会存放入指定的变量。使用
方法为:
ON_PARSE_COMMAND(Add, CTestExtension, ITS_PSTR ITS_I4)
ON_PARSE_COMMAND_PARAMS("name id")
ON_PARSE_COMMAND宏中需要指明函数名,类名和参数类型列表,ON_PARSE_COMMAND_PAR
AMS宏中需要根据前一个宏中所列出的参数列表来指明表单中的变量名称列表。最后一步
就是定义一个名称与请求URL中?后命令名称相同的成员函数,参数的设置要与ON_PARSE
_COMMAND宏中的参数列表定义相符合,在这个例子中为:
void CTestExtension::Add(CHttpServerContext* pCtxt,LPTSTR pszName,int iID)。
参数类型列表中可以使用下面的类型后面为该类型的说明:
ITS_EMPTY 无数据
ITS_PSTR 字符串LPCSTR
ITS_I2 short
ITS_I4 long
ITS_R4 float
ITS_R8 double
下面我们看一个更复杂的表单,表单定义如下:
<FORM ACTION="test.dll?Delete" METHOD=POST>
<INPUT NAME="name">
<INPUT NAME="month">
<SELECT NAME="mode">
<OPTION VALUE=1>All
<OPTION VALUE=2>Before
<OPTION VALUE=3>After
<INPUT TYPE=HIDDEN NAME=pwd VALUE=xxx>
<INPUT TYPE=SUBMIT>
</FORM>
定义映射和处理函数如下:
ON_PARSE_COMMAND(Add, CTestExtension, ITS_PSTR ITS_I4 ITS_I4 ITS_PSTR)
ON_PARSE_COMMAND_PARAMS("name month mode pwd")
void CTestExtension::Add(CHttpServerContext* pCtxt,LPTSTR pszName,int iMonth
,int iMode,LPTSTR pszPwd)。
ISAPI程序的输出:在所有的命令处理函数中第一个参数都是CHttpServerContext*指针
,我们所有的输出都要通过它进行,在CHttpServerContext类中定义了<<操作符,通过
该操作符我们可以方便的输出字符串,数字,二进制数据。输出的方法为:
*pCtxt<<"this is a string";
*pCtxt<<'c';
*pCtxt<<10;
可以看得出输出是很简单的,一个完整的输出过程应该是如同下面的形式:
StartContent(pCtxt);//开始输出
WriteTitle(pCtxt);//输出头部信息,相当于输出<TITLE>
*pCtxt << "your string";
EndContent(pCtxt);//结束输出
我们所使用的ISAPI扩展类是由CHttpServer所派生,可以调用CHttpServer::AddHeader
来指明返回数据的类型,例如下面的代码演示了输出纯文本:
void CTestisaExtension::Default(CHttpServerContext* pCtxt)
{
AddHeader(pCtxt, "Content-type = text/plain\r\n");
(*pCtxt) << "Hello world!\r\n";
}
我们可以重载某些函数来达到加强控制的目的,可重载的函数有以下这些:
virtual LPCTSTR CHttpServer::GetTitle( ) const;返回<TITLE>部分信息
virtual BOOL CHttpServer::OnParseError( CHttpServerContext* pCtxt, int nCaus
e );错误处理
virtual void CHttpServer::StartContent( CHttpServerContext* pCtxt ) const;输
出<HTML><BODY>部分信息
virtual void CHttpServer::EndContent( CHttpServerContext* pCtxt ) const;输出
</BODY></HTML>部分信息
virtual void CHttpServer::WriteTitle( CHttpServerContext* pCtxt ) const;输出
<TITLE></TITLE>部分信息
此外我们可以在命令处理函数中利用CHttpServerContext指针来得到CGI中的相关环境变
量,在CHttpServerContext中有一个成员变量m_pECB为下面的结构指针。
typedef struct _EXTENSION_CONTROL_BLOCK {
DWORD cbSize; //IN 该结构长度
DWORD dwVersion //IN 版本
HCONN ConnID; //IN 连接上下文
DWORD dwHttpStatusCode; //OUT 状态码
CHAR lpszLogData[HSE_LOG_BUFFER_LEN]; //OUT
LPSTR lpszMethod; //IN 环境变量REQUEST_METH
OD
LPSTR lpszQueryString; //IN QUERY_STRING
LPSTR lpszPathInfo; //IN PATH_INFO
LPSTR lpszPathTranslated; //IN PATH_TRANSLATED
DWORD cbTotalBytes; //IN CONTENT_LENGTH
DWORD cbAvailable; //IN
LPBYTE lpbData; //IN
LPSTR lpszContentType; //IN CONTENT_TYPE
...其他信息在此忽略
} EXTENSION_CONTROL_BLOCK, *LPEXTENSION_CONTROL_BLOCK;