Reader's Digest

Digest your Internet

ASP中巧用Response属性

Written By: dch1 - May• 01•08
—- 我在用ASP为某单位制作网页时遇到这样一个问题,单位以前的MIS系统中将一些Word文件以字节流的形式保存在数据库中,现在用户要求我用ASP将这些Word文件数据从数据库中取出并在网页中显示出来。开始我自然地想到在服务器上创建临时文件、然后在网页中增加一个指向这个临时文件的链接,但这个方法将大大增加服务器的负担不说,而且在服务上如何保证特定客户端所使用的临时文件不被其它客户端使用的文件覆盖,如何在文件传送给用户后将文件删除,这些问题在实际都难很好解决。那么有没有更好的办法呢?

—- 为此我仔细查看了一下ASP的参考书,发现Response对象有一个叫contenttype的属性,它定义服务器发送给客户端内容的MIME类型。MIME全称Multipurpose Internet Mail Extensions,即多功能Internet邮件扩展。我们知道,在网页编程中我们有时将超链接指向一个Word或Excel文件,当用户点击这个链接时浏览器会自动调用对应方法将这个文件打开。之所以能做到这点就是因为用户机器上安装office后会在浏览器中注册对应的MIME资源类型。比如说word文件的MIME类型是Application/msword(前者是MIME类型,后者是MIME子类),Excel文件的MIME资源类型是Application/msexcel。事实上,凡是浏览器能处理的所有资源都有对应的MIME资源类型,比如说html文件的MIME类型是Text/html,JPG文件的MIME类型是Image/JPG。在与服务器的交互中,浏览器就是根据所接受数据的MIME类型来判断要进行什么样的处理,对html、JPG等文件浏览器直接将其打开,对Word、Excel等浏览器自身不能打开的文件则调用相应方法打开。对没有标记MIME类型的文件,浏览器则根据其扩展名和文件内容猜测其类型。如果浏览器无法猜出,则将它作为application/octet-stream。要了解各种文件的MIME类型,请在win98 我的电脑->查看->文件夹选项->文件类型 中查看。

—- 于是我灵机一动,想到在ASP中可以先将WORD数据以字节流方式取出,接着将其conntenttype属性标记为Application/msword,再将它发送给客户机,客户机收到这个资源后,根据其MIME类型,会自动调用客户机上的Word(当然,前提是客户机上装了Word,否则会将其作为一个不能识别的资源,提示用户保存起来,而不是打开它)将它打开。经试验效果很好,方法简单且速度很快,而且在IE5中浏览器使用内嵌方式(类似于OLE方式)打开,效果更佳。以下是程序内容。

—- 假设表名tab_word,表中有两个字段,一个是整型,名id,用作Word数据的唯一标识,另一个Blob型,名worddata,里面存放Word数据。现在要在页面上显示id等于1的Word文件内容, ASP程序如下:

    < %
    ´ conn – 已创建的数据库连接
    ´ rs  —  结果集
    rs = conn.execute(“select
    worddata from tab_word where id = 1”)
    response.contenttype = “Application/msword”
    response.writebinary(rs(“worddata”))
    ´注意将结果集中的数据直接用writebinary发送出去,不要用变量
    ´接收这个数据,否则系统会报错
    % >

—- 用类似的方法,还可以处理Excel、Bmp等许多类型的数据。此程序在以下系统中测试通过:服务器:NT + IIS + SqlServer客户端:Win98 + IE5 或 Netscape4.x

如何用ASP编写网站统计系统

Written By: dch1 - May• 01•08
在目前的网站统计系统决大部分都是CGI的,但编写起来特别复杂,而ASP学起来简单,更有和数据库结合的优点,所以结合自己曾经做过的网站统计系统,和大家探讨一下ASP编写网站统计系统。

  大家都看过网易的网站统计系统,它可以统计总访问量,每日平均访问量,当日访问量,最高访问量,最高访问日期,日流量分析,月流量分析,周流量分析,浏览器分析,等等。

  其实要做一个ASP的访问统计系统关键是系统表结构的设计。以及如何来采集用户的CGI变量,如何来显示用户的信息。也就是说系统的关键是两个ASP程序,统计程序和显示程序。

  首先我们先看看如何来采集用户的访问信息。

  我们编写访问统计需要知道用户的如下信息,访问者的IP(根据访问IP可以形成访问者IP列表),访问者的浏览器与操作系统(统计访问者的浏览器与操作系统及所有访问者浏览器与操作系统比例图),访问者的访问时间(进行日访问量分析,月访问量分析,周访问量分析),下面我们来看看用ASP的获得以上信息的语句:
  1。获得访问者IP
  Dim M_IP
  M_IP=Request.Servervariables(“REMOTE_HOST”)
  用上面的语句可以取得访问者的IP。
  2。获得浏览器信息
  Dim O_Browser,M_BrowserType
  Set O_Browser=Server.Createobject(“MSWC.BrowserType”)
  M_BrowserType=O_Browser.Browser+O_Browser.Version
  3。获得访问时间
  Dim M_DateTime
  M_DateTime=Year(Date())&”/”&Right(“0″&Month(Date()),2)&”/”Right(“0″&Day(Date()),2)&”/”&Right(“0″&Hour(Time()),2)&”:”&Right(“0″&Minute(Time()),2)&”:”&Right(“0″&Second(Time()),2)

  1 取得用户的操作系统。
  在ASP中使用如下语句可以得到访问者的http_user_agent字符串。
  Dim StrUserAgent
  StrUserAgent=Request.ServerVariables(“HTTP_USER_AGENT”)
  这个字符串一般是如下格式:
  Mozilla/4.0 (compatible; MSIE 4.01; Windows 98)
  上面的字符串可以说明访问者使用的操作系统是Windows98,浏览器是MSIE 4.01,但是这个字符串格式不固定,而且可以自己更改。
  平常我们所见的其它一些主要的UserAgent字符串如下:
  使用IE的浏览器:
  Mozilla/2.0 (compatible; MSIE 3.01; Windows 95)
  Mozilla/4.0 (compatible; MSIE 4.0; Windows 95);
  Mozilla/4.0 (compatible; MSIE 4.01; Windows 98)
  Mozilla/4.0 (compatible; MSIE 5.0; Windows 98);
  Mozilla/4.0 (compatible; MSIE 5.0b2; Windows NT)
  使用NetScape的浏览器:
  Mozilla/4.03 〔en〕 (Win95; I)
  Mozilla/4.08 〔en〕 (WinNT; U ;Nav)
  Mozilla/4.5 〔en〕 (WinNT; U)
  Mozilla/3.04Gold (Win95; I)
  使用Opera的浏览器:
  Mozilla/4.0 (compatible; Opera/3.0; Windows 95) 3.50b10
  FrontPage编辑器:
  Mozilla/2.0 (compatible; MS FrontPage 3.0)
  使用Sun操作系统:
  Mozilla/3.01Gold (X11; I; SunOS 5.7 i86pc)
  使用PowerPc的Mac机:
  Mozilla/4.0 (compatible; MSIE 4.5; Mac_PowerPC)
  通过分析以上字符串,我们可以找出规律,编写一个子程序来判断访问者用的是何种操作系统,又由于用ASP中的判断浏览器类型的控件需要更新Browser.ini文件,所以我们可以结合这个字符串来判断浏览器属性。

  2.我们以什么样的方式来统计网站呢?

  我们可以让用户在他的主页上加入如下语句:
  <a href=”http://www.abc.com/viewer.asp?userid=username”><img src=”http://www.abc.com/counter.asp?userid=username”></a>上面的userid是具体哪一个用户,要注意用户和访问者不是一个概念。
  通过上面的字符串我们就可以采集用户的访问数据,并给用户提供观看数据的链接。在我们看加有网易的统计系统的页面时会发现它会返回给用户一个图标,我们就可以在counter.asp中实现这个功能。
  加入:response.redirect “http://www.abc.com/abc.gif”
  这个语句我们可以加在统计数据采集后返回给用户。
  
  设计表结构是一项极其重要的工作,它的合理与否与程序的编制紧密相关。
  一个网站统计系统应该有一个用户表,统计值表。
  这个用户表也就是保留注册用户信息的表,统计值表就是记录用户的每一项统计指标值的表。在统计值的表中我们可以指定用户的统计指标,我们可把每一个指标用一个ID值来表示,这里我们简单举例。

用户表:
Table Name:regist_table

Field type
username C 用户名
password C 密码
regdate C 注册时间

值表:
Table Name:value_table
Field type
username C 用户名
id C 统计指标ID
value C 统计指标的值

Id列表:
Table Name:id_table
Field type
id C 统计指标ID
idvalue C 统计指标的说明

  有了这三个表我们就可以开始做了。

如我们可以指定以下ID
id idvalue
101 总访问量
201 1日访问量
202 2日访问量
: :
: :
231 31日访问量

  要想对用户开始统计我们必须得先让用户注册,用户使用的流程如下:
  填注册表->初始用户的value表(把对应的ID加入)->把注册信息反馈给用户
->用户在自己的页面上加入链接->开始统计

  能采集数据我们都能采到了,那么我们就开始编制ASP的统计页面。
  这一页我们叫计数页,counter.asp
  这段asp代码我们需要让它按如下的流程进行采集数据并保存数据和更新数据:
  采集用户名,判断用户名是否合法,采集访问者的信息,对信息进行加工,进行保存和更新数据库,返回logo图标。
  调用这个ASP用counter.asp?user=abc这个方式。
  采集用户名我们可以用Request对象的相应方法取得,然后检查用户表判断用户是否合法,然后取信息,用我们上面讲到的取得相应信息的方法取得信息,然后进行加工保存在数据表里,但最重要的是如何对数据进行更新,如当日每小时访问统计数,当天每小时统计数等,我们如何对每天的数据进行更新是这个程式的要点,我们可以采取几种方式,如对每天的每个小时的记录的更新我们采取在每天午夜12点更新,对每月的每一天的数据我们在月份切换的那一天进行更新。

在Web页面中执行Windows程序

Written By: dch1 - May• 01•08
现在许多公司都面临一个难题:如何在Web环境中执行存在的Windows应用程序。这里就介绍实现这个功能的技术,它争取对代
码做最小的改变,完成在Windows环境中应做的一切。

现存的Windows应用程序

  这里想要在Web中执行的Windows例子程序是非常简单的,它是用VB编写的,其中有一个表单。运行时,在表单上显示雇员的信
息,这些信息来源于Access数据库的一个表。表单上设有First、Next、Previous 和 Last按钮,从而允许用户浏览记录。同时,
还可以通过按钮Add、Delete 和 Update来改变数据。

这个程序通过一个COM类来与数据库通信,它有下面的方法:

AddEmployee() 在表中添加一个记录,保存新雇员的信息
UpdateEmployee() 更新一个记录
DeleteEmployee() 删除一个记录
GetEmployees() 获取一个雇员的信息

程序正常运行时,浏览器显示如下:

开发Web应用程序

  在传统的web应用程序中,大多数的处理都是在服务器端完成的。这里,我们将尝试在客户端做一些处理,以减少服务器上的工
作量。也就是,让客户端完成显示信息的处理工作,并将商业规则和数据库存取留给服务器端。这就象一个n层处理模型。

  当用户需要访问另一个不同的数据时,我们也不想从服务器上再调入整个web页面,因此,需要找到一个web客户端在后台与
web服务器交流信息的方法。这个例子中,我们使用了微软公司的XMLHTTP COM对象组件,它是随Internet Explorer 5.0而来
的。当然,也可以编写一个功能类似的Java applet来克服这个局限。

服务器端的代码

  让我们从研究VB应用程序的COM类到Web的每一个方法开始,这可以通过编写ASP页面来调用COM类中的每个方法实现
(AddEmployee.asp, UpdateEmployee.asp, DeleteEmployee.asp, GetEmployee.asp)。 明白了这些,就能够在Web中存取COM
类方法了。

  ASP页面应该能够接受与COM类一样的参数,这些页面向原始的COM类发送调用。这里主要的区别就是所有的输出是以XML格式
的。我们使用另外一个叫XMLConverter的COM类,转换方法的输出为XML格式。XMLConverter的代码包含在下载文件中,它有一个
函数,能够接受一个ADO记录集做为参数,并且转换为一个XML文档。实现这个目的的函数例子可以从Internet上很容易地找到,比
如:

http://www.vbxml.com/xml/guides/developers/ado_persist_xml.asp

  我们也许曾经使用过ADO记录集的Save函数,加上adPersistXML,来实现按照xml格式保存,但是在这里,为了简单起见,我
们仍使用编制的函数。

下面的代码来自GetEmployees.asp,它执行GetEmployees方法,从而可以让你清晰地看到这种技术:

<SCRIPT LANGUAGE=vbscript RUNAT=Server>
‘Declare the above described XMLConverter
Dim objXMLConverter

‘Create the XMLConverter object on the web server machine
Set objXMLConverter = Server.CreateObject(“XMLConverter.clsXMLConverter”)

‘Declare the above described EmployeeMgr object
Dim objEmployeeMgr

‘Create the EmployeeMgr object on the web server machine
Set objEmployeeMgr = Server.CreateObject(“EmployeeMgr.clsEmployeeMgr”)

‘Declare a String varaible
Dim strXML

   现在调用Employees对象的Employees()方法,它将返回一个ADO记录集对象,我们将这个对象传递给XMLConverter对象的
xmlRecordset()方法,xmlRecordset()负责将ADO记录集转换为XML文档。最后,我们取回XML文档,并将它存入strXML字符
串变量中:

strXML = objXMLConverter.xmlRecordset(objEmployeeMgr.GetEmployees)

‘Destroy the EmployeeMgr object
Set objEmployeeMgr = Nothing

‘Destroy the XMLConverter object
Set objXMLConverter = Nothing

‘Write the XML Document as the response
Response.Write strXML
</SCRIPT>

然后,用同样的方式来创建页面AddEmplyee.asp、DeleteEmployee.asp和UpdateEmployee.asp。

客户端的代码

  现在准备编写客户端代码,首先,让我们仔细看看VB应用程序在调用后如何显示信息。在VB表单的On_Load方法(参见下面的
代码)中,我们调用了COM对象组件GetEmployees方法,这个方法返回一个附带雇员信息的ADO记录集。ADO记录集的MoveFirst
()、MoveNext()以及 MoveLast() 方法建立了记录浏览的方法。

Private Sub Form_Load()
‘Create the EmployeeMgr Object
Set objEmplyeeMgr = New clsEmployeeMgr

‘Obtain the Employee Records in a ADODB.Recordset
Set rst = objEmplyeeMgr.GetEmployees
rst.MoveFirst
DisplayCurrentRecord
End Sub

   在这种情况下,我们有一个ASP页面GetEmployees.asp,它给出了做为XML文档的信息。所以我们将在web客户端建立一个
XMLDOM对象,并且调入由GetEmployees.asp提供的信息。在这个例子中,我们使用Microsoft DOM XML来解析。关于DOM XML解
析的完整文档,请参考MSDN有关文章,比如 XML DOM Objects。

  另一个较好的解决方法是使用纯Java/JavaScript,它同时可以在非Internet Explorer的浏览器上应用。这里,我们仍使用
XMLHTTP对象,它可以让web客户端建立一个到web服务器的HTTP请求。关于对XML HTTP的详细描述,请参考MSDN上的文档。

//Create an XMLDOM on the Web Client machine
var xmlDoc = new ActiveXObject(“Microsoft.XMLDOM”);

// node pointing at Root node of the XML Document
var nodeRoot;

// node to point at Current Record
var nodeCurrentRecord;

// Integer pointing at the current Record number
var nCurrentIndex = 0;

//Create the Microsoft XMLHTTP object on the web client machine
//This would have to be present and registered on the client machine
//Installing Internet Explorer 5.0 satisfies this requirement
var objHTTPRequest = new ActiveXObject(“Microsoft.XMLHTTP”);

//Open a http connection to the URL in strURL
objHTTPRequest.Open (“GET”, strURL, false, null, null);

//Send the request
objHTTPRequest.send();

//Obtain the response received to the xmlResponse variable
//This response would be the XML document returned by the web server
var xmlResponse = objHTTPRequest.responseText

//Since the response is an XML document we can load it to an xmlDoc object
xmlDoc.loadXML (xmlResponse);

//Set nodeRoot to point at the root of the xml document
nodeRoot = xmlDoc.documentElement;

   从上面我们了解了XML文档的结构,现在可以仔细研究XML文档对象了。我们将编写一个客户端的JavaScript函数
rstMoveFirst(),它可以移动当前记录指针到第1条,这与ADO记录集的MoveFirst方法类似:

function rstMoveFirst() {
//Error trap for empty record set
if (nodeRoot.childNodes.length; < 1) {

//If the root node does not have any child nodes then there are
//no “records”
return false;
}
nCurrentIndex = 0;

//Set the nodeCurrentRecord to point at the 0th child of the
//XML Document. The 0th child would be the first record.
// nodeRoot is the XML document? documentElement
nodeCurrentRecord = nodeRoot.childNodes(nCurrentIndex);

//Return Success
return true;
}

   同样,我们可以编写rstMoveNext()和 rstMoveLast()函数,通过编写这些代码,我们将能仔细地了解XML文档元素。而且,
再编写一个类似于ADO记录集upadte方法的函数。

  现在我们在客户机上创建了一个假冒的ADO记录集对象,因此就可以象在VB应用程序中一样来处理这些“记录集”。

  有了这些函数,剩下的就是编写用户界面,这就象在VB应用程序中一样。比如,在VB应用程序中,“移动到第1条记录”后面
的代码是:

Private Sub btnFirst_Click()
If Not (rst.EOF And rst.BOF) Then

‘Move to the first record
rst.MoveFirst

‘DisplayCurrentRecord is a function that display the current ‘records information
DisplayCurrentRecord

End If
End Sub

在web应用程序中,相应的代码是:

function btnFirstClick() {
‘Move to the first record in the recordset
‘Note that our rstMoveFirst returns True if
‘it was successful and false if EOF and BOF
if (rstMoveFirst()) {
‘Here DisplayCurrentRecord is client side JavaScript
‘function that display the current records information on
‘the the screen
DisplayCurrentRecord();
}
}

  当需要更新实际的数据库时,就发送更新信息给UpdateEmployee.asp,这个页面将通过COM对象的UpdateEmployee方法来更
新数据库。上面描述的应用程序,输出到web上,将显示如下图:

结论

  在web应用中,要建立适当的计划来转换ADO记录集为XML文档。一旦定义明确了,象那样标准的应用将很好实现。另外一个我
们想研究的领域是客户端记录集的操纵函数(就是rst*函数)。我们可以编写Java applet来处理这些记录集操纵函数,从而在客
户端建立了Java记录集对象。这种方法将是很面向对象的一种处理方法。