文件上传是Web应用程序中一个非常实用的功能,它允许用户从客户端机器上传任意文件到Web服务器。为了实现这一功能,客户端的表单需要使用"multipart/form-data"编码方式提交。然而,ASP的Request.Form对象并不支持这种编码类型,因此需要第三方组件来解决这个问题。但是,这些第三方组件往往存在一些问题,比如丢弃与上传文件无关的其他重要表单数据,不支持多文件上传,与现有的Request.Form接口不一致,以及不支持从上传的文件中读取块数据(这对于将大文件上传到数据库的BLOB字段非常有用)。
为了避免这些问题,开发了一个COM对象,用户可以在"multipart/form-data"编码的情况下使用它,而不是Request.Form。在开发这个COM对象时,尽量避免了上述问题。但是,提供的解决方案并不会完全替代Request.Form,而是一个补充方案,用户可以在需要"multipart/form-data"编码的情况下使用。用户仍然可以在其他编码类型的情况下使用Request.Form。
"multipart/form-data"这种编码类型在RFC1867中有描述,它描述了如何在HTTP协议上实现文件上传。要启用文件上传,表单的enctype应该设置为multipart/form-data,方法应该设置为post。然后,输入标签应该是file类型。以下是表单的示例代码:
<form method="post" action="upload.asp" enctype="multipart/form-data">
<input name="name" value="Al-Mutairi, Fayez">
<input name="email" value="fayezmm@yahoo.com">
<input name="file" type="file">
<input name="submit" type="submit" value="Submit">
</form>
当用户点击提交按钮时,Web服务器将接收到以下数据:
-----------------------------7d1f5a80420
Content-Disposition: form-data; name="name"
Al-Mutairi, Fayez
-----------------------------7d1f5a80420
Content-Disposition: form-data; name="email"
fayezmm@yahoo.com
-----------------------------7d1f5a80420
Content-Disposition: form-data; name="file"; filename="C:\folder_icon.gif"
Content-Type: image/gif
[二进制文件内容]
-----------------------------7d1f5a80420
Content-Disposition: form-data; name="submit"
Submit
-----------------------------7d1f5a80420--
此时,upload.asp开始运行时,无法使用Request.Form访问表单数据,因此需要第三方组件的帮助。该组件将读取前面的请求,解析它,并构建一个可以类似访问Request.Form项的项集合。
让使用MyRequest.Form组件构建upload.asp:
<%@ LANGUAGE="JScript" %>
<%
var form = Server.CreateObject("MyRequest.Form");
form.Init();
Response.Write("Name = " + form("name"));
Response.Write("Email = " + form("email"));
var file = form.Item("file").Item(1);
Response.Write("FileName = " + file.FileName);
Response.Write("FileExt = " + file.FileExt);
Response.Write("FilePath = " + file.FilePath);
Response.Write("MimeType = " + file.ContentType);
Response.Write("FileSize = " + file.TotalBytes);
// ** To save into a file use Write method of the ADO Stream Object
var fileStream = Server.CreateObject("ADODB.Stream");
fileStream.Open();
fileStream.Type = adTypeBinary;
fileStream.Write(file.Value);
fileStream.SaveToFile(Server.MapPath("Uploaded Files") + "\\" + file.FileName, adSaveCreateOverWrite);
fileStream.Close();
//
**
To
save
into
a
database
use
AppendChunk
method
of
the
Field
Object
of
ADO
Recordset
var cn = Server.CreateObject("ADODB.Connection");
var rs = Server.CreateObject("ADODB.Recordset");
cn.Open("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + Server.MapPath("Database.mdb"));
rs.Open("Users", cn, adOpenForwardOnly, adLockOptimistic, adCmdTable);
rs.AddNew();
rs.Fields("id") = 1000;
rs.Fields("name") = form("name").Value;
rs.Fields("email") = form("email").Value;
rs.Fields("FileType") = file.ContentType;
rs.Fields("file").AppendChunk(file.Value);
rs.Update();
rs.Close();
%>
以下是IForm接口的方法描述:
Method Description
Init(VARIANT varBinary) Initialize the form with posted data. varBinary is optional it is = Request.BinaryRead(Request.TotalBytes)
Item(VARIANT Index, IListItem** ppItem) (Default method) Returns the ListItem object with the specified key either as the item name or index.
Count(long* pVal) Number of listitem's objects.
以下是IListItem接口的方法描述:
Method Description
Value(VARIANT* pValue) (Default method) Item's value.
Item(long lIndex, IItem** ppItem) Returns the Item object with the specified index.
Count(long* pVal) Number of item's objects.
Name(BSTR* pName) Item's name.
Method Description
Value(VARIANT* pValue) (Default method) Return the value of the item.
IsFile(BOOL *pVal) Return TRUE if the Item object is a file otherwise it returns FALSE.
FileName(BSTR *pVal) The name of the uploaded file. AVALIABLE ONLY if object is a file.
FilePath(BSTR *pVal) The path of the uploaded file. AVALIABLE ONLY if object is a file.
FileExt(BSTR *pVal) The extension of the uploaded file. AVALIABLE ONLY if object is a file.
ContentType(BSTR *pVal) The content-type (MIME TYPE) of the uploaded file. AVALIABLE ONLY if object is a file.
TotalBytes(long *pVal) Size in bytes of the uploaded file. AVALIABLE ONLY if object is a file.
GetChunk(long offset, long length, VARIANT* pChunk) Return a chunk of the file with the specified size and position. AVALIABLE ONLY if object is a file.