七彩课堂[网页设计ASP.NET教程系列]
用纯ASP代码实现图片上传
       用ASP编写网站应用程序时间长了,难免会遇到各式各样的问题,其中关于如何上传文件到服务器恐怕是遇见最多的问题了,尤其是上传图片,比如你想要在自己的社区里面实现类似网易虚拟社区提供的“每日一星”的功能,就要提供给网友上传照片的功能。上传图片文件到服务器可以使用各种免费的文件上传组件,使用起来功能虽然很强大,但是由于很多情况下,我们只能使用免费的支持ASP的空间或者租用别人的虚拟空间,对于第一种情况,我们根本就没有可能来使用文件上传组件;至于第二种情况,我们也要付出不少的“银子”才可以。除非你拥有自己的虚拟主机,你就可以随便的在服务器上面安装自己所需要的组件,这种情况对于大多数人来说是可望而不可及的。那我们就没有办法了吗?呵呵,答案是肯定的(当然是肯定的了,要不然我也没法写出这篇文章啊)。
下面就让我们一起来使用纯ASP代码来实现图片的上传以及保存到数据库的功能(顺便也实现显示数据库中的图片到网页上的功能)。
   首先我们先来熟悉一下将要使用的对象方法。我们用来获取上一个页面传递过来的数据一般是使用Request对象。同样的,我们也可以使用Request对象来获取上传上来的文件数据,使用的方法是Request.BinaryRead()。而我们要从数据库中读出来图片的数据显示到网页上面要用到的方法是:
Request.BinaryWrite()。在我们得到了图片的数据,要保存到数据库中的时候,不可以直接使用Insert语句对数据库进行操作,而是要使用ADO的AppendChunk方法,同样的,读出数据库中的图片数据,要使用GetChunk方法。各个方法的具体语法如下:
*Request.BinaryRead语法:
variant=Request.BinaryRead(count)
参数
variant
返回值保存着从客户端读取到数据。
count
指明要从客户端读取的数据量大小,这个值小于或者等于使用方法Request.TotalBytes得到的数据量。
*Request.BinaryWrite语法:
Request.BinaryWritedata
参数
data
要写入到客户端浏览器中的数据包。
*Request.TotalBytes语法:
variant=Request.TotalBytes
参数
variant
返回从客户端读取到数据量的字节数。
*AppendChunk语法
将数据追加到大型文本、二进制数据Field或Parameter对象。
object.AppendChunkData
参数
objectField或Parameter对象
Data变体型,包含追加到对象中的数据。
说明
使用Field或Parameter对象的AppendChunk方法可将长二进制或字符数
   据填写到对象中。在系统内存有限的情况下,可以使用AppendChunk方法对长整型值进行部分而非全部的操作。
*GetChunk语法
返回大型文本或二进制数据Field对象的全部或部分内容。
variable=field.GetChunk(Size)
返回值
返回变体型。
参数
Size长整型表达式,等于所要检索的字节或字符数。
说明
   使用Field对象的GetChunk方法检索其部分或全部长二进制或字符数据。在系统内存有限的情况下,可使用GetChunk方法处理部分而非全部的长整型值。
GetChunk调用返回的数据将赋给“变量”。如果Size大于剩余的数据,则
GetChunk仅返回剩余的数据而无需用空白填充“变量”。如果字段为空,则
GetChunk方法返回Null。
   每个后续的GetChunk调用将检索从前一次GetChunk调用停止处开始的数据。但是,如果从一个字段检索数据然后在当前记录中设置或读取另一个字段的值,ADO将认为已从第一个字段中检索出数据。如果在第一个字段上再次调用GetChunk方法,ADO将把调用解释为新的GetChunk操作并从记录的起始处开始读取。如果其他Recordset对象不是首个Recordset对象的副本,则访问其中的字段不会破坏GetChunk操作。
如果Field对象的Attributes属性中的adFldLong位设置为True,则可以对该字段使用GetChunk方法。
如果在Field对象上使用Getchunk方法时没有当前记录,将产生错误3021(无当前记录)。
   接下来,我们就要来设计我们的数据库了,作为测试我们的数据库结构如下(access2000):
字段名称    类型    描述
   id   自动编号   主键值
img OLE对象   用来保存图片数据 

对于在MSSQLServer7中,对应的结构如下:
字段名称    类型    描述
   id    int(Identity)  主键值
img   image    用来保存图片数据 
现在开始正式编写我们的纯ASP代码上传部分了,首先,我们有一个提供给用户的上传界面,可以让用户选择要上传的图片。代码如下
(upload.htm):
<html>
<body>
<center>
<form name="mainForm" enctype="multipart/form-data" action="process.asp" method=post>
   <inputtype=filename=mefile><br>
   <inputtype=submitname=okvalue="OK">
</form>
</center>
</body>
</html>
注意enctype="multipart/form-data",一定要在Form中有这个属性,否则,将无法得到上传上来的数据。接下来,我们要在process.asp中对从浏览器中获取的数据进行必要的处理,因为我们在process.asp中获取到的数据不仅仅包含了我们想要的上传上来的图片的数据,也包含了其他的无用的信息,我们需要剔除冗余数据,并将处理过的图片数据保存到数据库中,这里我们以access2000为例。具体代码如下(process.asp):
<%
response.buffer=true
formsize=request.totalbytes
formdata=request.binaryread(formsize)
bncrlf=chrB(13)&chrB(10)
divider=leftB(formdata,clng(instrb(formdata,bncrlf))-1)
datastart=instrb(formdata,bncrlf&bncrlf)+4
dataend=instrb(datastart+1,formdata,divider)-datastart
mydata=midb(formdata,datastart,dataend)
setconnGraph=server.CreateObject("ADODB.connection")
connGraph.ConnectionString="driver={MicrosoftAccessDriver(*.mdb)}; DBQ="&server.MapPath("images.mdb")&";uid=;PWD=;"
connGraph.Open
setrec=server.createobject("ADODB.recordset")
rec.Open"SELECT*FROM[images]whereidisnull",connGraph,1,3
rec.addnew
rec("img").appendchunkmydata
rec.update
rec.close
setrec=nothing
setconnGraph=nothing
%>
好了,这下我们就把上传来的图片保存到了名为images.mdb的数据库中了,剩下的工作就是要将数据库中的图片数据显示到网页上面了。一般在HTML中,显示图片都是使用<IMG>标签,也就是<IMGSRC="图片路径">,但是我们的图片是保存到了数据库中,“图片路径”是什么呢?呵呵,其实这个SRC属性除了指定路径外,也可以这样使用哦:
<IMGSRC="showimg.asp?id=xxx">
所以,我们所要做的就是在showimg.asp中从数据库中读出来符合条件的
数据,并返回到SRC属性中就可以了,具体代码如下(showimg.asp):
<%
setconnGraph=server.CreateObject("ADODB.connection")
connGraph.ConnectionString="driver={MicrosoftAccessDriver(*.mdb)};DBQ="&
server.MapPath("images.mdb")&";uid=;PWD=;"
connGraph.Open
setrec=server.createobject("ADODB.recordset")
strsql="selectimgfromimageswhereid="&trim(request("id"))
rec.openstrsql,connGraph,1,1
Response.ContentType="image/*"
Response.BinaryWriterec("img").getChunk(7500000)
rec.close
setrec=nothing
setconnGraph=nothing
%>
注意在输出到浏览器之前一定要指定Response.ContentType="image/*",
以便正常显示图片。
最后要注意的地方是,我的process.asp中作的处理没有考虑到第一页(upload.htm)中还有其他数据,比如<INPUT type=tesxt name=userid>等等,如果有这些项目,你的process.asp就要注意处理掉不必要的数据。

另外一方法:
无组件上传
upload.asp
<SCRIPT RUNAT=SERVER LANGUAGE=VBSCRIPT>
Function GetUpload(FormData)
Dim DataStart,DivStr,DivLen,DataSize,FormFieldData
'分隔标志串(+CRLF)
DivStr = LeftB(FormData,InStrB(FormData,str2bin(VbCrLf)) + 1)
'分隔标志串长度
DivLen = LenB(DivStr)
PosOpenBoundary = InStrB(FormData,DivStr)
PosCloseBoundary = InStrB(PosOpenBoundary + 1,FormData,DivStr)
Set Fields = CreateObject("Scripting.Dictionary")

While PosOpenBoundary > 0 And PosCloseBoundary > 0
'name起始位置(name="xxxxx"),加6是因为[ name=" ]长度为6
FieldNameStart = InStrB(PosOpenBoundary,FormData,str2bin("name=")) + 6
FieldNameSize = InStrB(FieldNameStart,FormData,ChrB(34)) - FieldNameStart '(")的ASC值=34
FormFieldName = bin2str(MidB(FormData,FieldNameStart,FieldNameSize))

'filename起始位置(filename="xxxxx")
FieldFileNameStart = InStrB(PosOpenBoundary,FormData,str2bin("filename=")) + 10
If FieldFileNameStart < PosCloseBoundary And FieldFileNameStart > PosopenBoundary Then
FieldFileNameSize = InStrB(FieldFileNameStart,FormData,ChrB(34)) - FieldFileNameStart '(")的ASC值=34
FormFileName = bin2str(MidB(FormData,FieldFileNameStart,FieldFileNameSize))
Else
FormFileName = ""
End If

'Content-Type起始位置(Content-Type: xxxxx)
FieldFileCTStart = InStrB(PosOpenBoundary,FormData,str2bin("Content-Type:")) + 14
If FieldFileCTStart < PosCloseBoundary And FieldFileCTStart > PosOpenBoundary Then
FieldFileCTSize = InStrB(FieldFileCTStart,FormData,str2bin(VbCrLf & VbCrLf)) - FieldFileCTStart
FormFileCT = bin2str(MidB(FormData,FieldFileCTStart,FieldFileCTSize))
Else
FormFileCT = ""
End If

'数据起始位置:2个CRLF开始
DataStart = InStrB(PosOpenBoundary,FormData,str2bin(VbCrLf & VbCrLf)) + 4
If FormFileName <> "" Then
'数据长度,减1是因为数据文件的存取字节数问题(可能是AppendChunk方法的问题):
'由于字节数为奇数的图象存到数据库时会去掉最后一个字符导致图象不能正确显示,
'字节数为偶数的数据文件就不会出现这个问题,因此必须保持字节数为偶数。
DataSize = InStrB(DataStart,FormData,DivStr) - DataStart - 1
FormFieldData = MidB(FormData,DataStart,DataSize)
Else
'数据长度,减2是因为分隔标志串前有一个CRLF
DataSize = InStrB(DataStart,FormData,DivStr) - DataStart - 2
FormFieldData = bin2str(MidB(FormData,DataStart,DataSize))
End If

'建立一个Dictionary集存储Form中各个Field的相关数据
Set Field = CreateUploadField()
Field.Name = FormFieldName
Field.FilePath = FormFileName
Field.FileName = GetFileName(FormFileName)
Field.ContentType = FormFileCT
Field.Length = LenB(FormFieldData)
Field.Value = FormFieldData

Fields.Add FormFieldName, Field

PosOpenBoundary = PosCloseBoundary
PosCloseBoundary = InStrB(PosOpenBoundary + 1,FormData,DivStr)
Wend
Set GetUpload = Fields
End Function

'把二进制字符串转换成普通字符串函数
Function bin2str(binstr)
Dim varlen,clow,ccc,skipflag
'中文字符Skip标志
skipflag = 0
ccc = ""
If Not IsNull(binstr) Then
varlen = LenB(binstr)
For i = 1 To varlen
If skipflag = 0 Then
clow = MidB(binstr,i,1)
'判断是否中文的字符
If AscB(clow) > 127 Then
'AscW会把二进制的中文双字节字符高位和低位反转,所以要先把中文的高低位反转
ccc = ccc & Chr(AscW(MidB(binstr,i + 1,1) & clow))
skipflag = 1
Else
ccc = ccc & Chr(AscB(clow))
End If
Else
skipflag = 0
End If
Next
End If
bin2str = ccc
End Function

'把普通字符串转成二进制字符串函数
Function str2bin(varstr)
str2bin = ""
For i = 1 To Len(varstr)
varchar = mid(varstr,i,1)
varasc = Asc(varchar)
' asc对中文字符求出来的值可能为负数,
' 加上65536就可求出它的无符号数值
' -1在机器内是用补码表示的0xffff,
' 其无符号值为65535,65535=-1+65536
' 其他负数依次类推。
If varasc < 0 Then
varasc = varasc + 65535
End If
'对中文的处理:把双字节低位和高位分开
If varasc > 255 Then
varlow = Left(Hex(Asc(varchar)),2)
varhigh = right(Hex(Asc(varchar)),2)
str2bin = str2bin & chrB("&H" & varlow) & chrB("&H" & varhigh)
Else
str2bin = str2bin & chrB(AscB(varchar))
End If
Next
End Function

'取得文件名(去掉Path)
Function GetFileName(FullPath)
If FullPath <> "" Then
FullPath = StrReverse(FullPath)
FullPath = Left(FullPath, InStr(1, FullPath, "\") - 1)
GetFileName = StrReverse(FullPath)
Else
GetFileName = ""
End If
End Function
</SCRIPT>
<SCRIPT RUNAT=SERVER LANGUAGE=JSCRIPT>
function CreateUploadField()
{
return new uf_Init()
}
function uf_Init()
{
this.Name = null
this.FileName = null
this.FilePath = null
this.ContentType = null
this.Value = null
this.Length = null
}
</SCRIPT>

conn.asp
<%
if Right(LCase(Request.ServerVariables("PATH_INFO")), 9) = "/conn.asp" then
Response.Write "你无权访问此页"
Response.End
else
dim ADOConn, ADOConnString
set ADOConn = Server.CreateObject("ADODB.Connection")
ADOConnString = "Provider=Microsoft.Jet.OLEDB.4.0; Data Source=" & Server.MapPath("/db/datebase.mdb")
ADOConn.Open(ADOConnString)
end if
%>

<!-- #include virtual="/inc/upload.asp" -->
<%
Dim FormSize, FormData, Form
FormSize = Request.TotalBytes
If FormSize > 0 then
FormData = Request.BinaryRead(FormSize)
Set Form = GetUpload(FormData)
If Form("src").FileName <> "" then
%>
<!-- #include virtual="/inc/adovbs.asp" -->
<!-- #include virtual="/inc/conn.asp" -->
<%
Dim ADOrs, SQL, ImageID
SQL = "images"
Set ADOrs = Server.CreateObject("ADODB.Recordset")
ADOrs.Open SQL, ADOconn, adOpenDynamic, adLockOptimistic, adCmdTable
ADOrs.AddNew
ADOrs("ContentType") = Form("src").ContentType
ADOrs("Length") = Form("src").Length
ADOrs("Date") = Date
ADOrs("Content").AppendChunk(Form("src").Value)
ADOrs.Update
ImageID = CStr(ADOrs("ID"))
ADOrs.Close
Set ADOrs = Nothing
%>
<!-- #include virtual="/inc/unconn.asp" -->
<%
Dim Src, Align, Alt, Border, Hspace, Vspace
Src = "showimage.asp?id=" & ImageID
Align = Form("align").Value
Alt = Form("alt").Value
If Form("border").Value = "" Then
Border = "0"
Else
Border = Form("border").Value
End If
If Form("hspace").Value = "" Then
Hspace = "0"
Else
Hspace = Form("hspace").Value
End If
If Form("vspace").Value = "" Then
Vspace = "0"
Else
Vspace = Form("vspace").Value
End If
Response.Write "<script language=""javascript"">" & VbCrLf
Response.Write " top.returnValue = '<img src=""" & Src & """ align=""" & Align & """ border=""" & Border & """ hspace=""" & Hspace & """ vspace=""" & Vspace & """ alt=""" & Alt & """ />';" & VbCrLf
Response.Write " top.close();" & VbCrLf
Response.Write "</script>" & VbCrLf
Response.End
End If
Set Form = Nothing
End If
%>
<?xml version="1.0" encoding="gb2312"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" >
<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
<title>图片</title>
<meta name="vs_defaultClientScript" content="JavaScript" />
<meta name="vs_targetSchema" content="HTML 4.0" />
<meta http-equiv="Content-Type" content="text/html; charset=gb2312" />
<style type="text/css">
<!--
body {
border: 0;
margin: 0;
background-color: buttonface;
}
body, td, input, select {
font-size: 12px;
}
fieldset {
padding: 6px;
}
legend {
font: smallcaption;
}
-->
</style>
<script language="JScript" type="text/jscript">
<!--
String.prototype.trim = function()
{
return this.replace(/(^\s*)|(\s*$)/g, "");
}
function isInt(text){
for (i = 0; i < text.length; i ++) if (!((text.charAt(i) >= '0') && (text.charAt(i) <= '9'))) return false;
return true;
}
function changenumber(input){
if (!isInt(input.value) && input.value.trim() != ''){
alert("无效的属性值");
input.focus();
input.select();
}
}
-->
</script>
</head>
<body bgcolor="buttonface" leftmargin="0" topmargin="0" marginwidth="0" marginheight="0" oncontextmenu="return false;">
<form method="post" enctype="multipart/form-data">
<table border="0" align="center" cellpadding="0" cellspacing="0">
<tr>
<td height="10" colspan="2">&nbsp;</td>
</tr>
<tr>
<td height="30" colspan="2"> <div align="left" valign="middle">图片来源(<u>P</u>):&nbsp;&nbsp;
<input name="src" type="file" id="src" style="width:320px; height:22px;" accesskey="P" size="25" valign="top" />
</div></td>
</tr>
<tr>
<td height="30" colspan="2"> <div align="left" valign="middle">替换文字(<u>T</u>):&nbsp;&nbsp;
<input type="text" name="alt" align="top" style="width:320px;height:18px;" accesskey="T" />
</div></td>
</tr>
<tr>
<td width="335" rowspan="2"> <table border="0" cellspacing="0" cellpadding="0" width="100%">
<tr>
<td><fieldset style="height:78">
<legend align="left">布局</legend>
<table>
<tr>
<td>&nbsp;对齐(<u>A</u>): &nbsp;&nbsp;&nbsp; <select name="align" accesskey="A" style="height:18px;">
<option>不设置</option>
<option value="left">左</option>
<option value="right">右</option>
<option value="textTop">文本上方</option>
<option value="absMiddle">正中央</option>
<option value="baseline" selected="selected">基线</option>
<option value="absBottom">正下方</option>
<option value="bottom">下</option>
<option value="middle">中</option>
<option value="top">上</option>
</select></td>
</tr>
<tr>
<td>&nbsp;边框宽度(<u>B</u>):
<input name="border" type="text" style="width:74px;height:18px;" accesskey="B" onblur="changenumber(this);" maxlength="5" /></td>
</tr>
</table>
</fieldset></td>
<td>&nbsp; </td>
<td><fieldset style="height:78">
<legend align="left">间隔</legend>
<table>
<tr>
<td valign="bottom">&nbsp;水平(<u>H</u>):&nbsp; <input type="text" name="hspace" size="5" accesskey="H" style="height:18px;" onblur="changenumber(this);" /></td>
</tr>
<tr>
<td valign="middle">&nbsp;垂直(<u>V</u>):&nbsp; <input type="text" name="vspace" size="5" accesskey="V" style="height:18px;" onblur="changenumber(this);" /></td>
</tr>
</table>
</fieldset></td>
</tr>
</table></td>
<td width="75" align="right" valign="bottom"> <input name="sub" type="submit" id="sub" style="width:65px;height:22px" value="确定" />
</td>
</tr>
<tr>
<td width="75" align="right" valign="bottom"> <input name="cancel" type="button" style="width:65px;height:22px" onclick="top.close();" value="取消" />
</td>
</tr>
</table>
</form>
</body>
</html>


 
信息推荐
资讯中心 | 电子商务 | 搜索营销 | 设计学院 | 中医养生 | 养生保健 | 节日祝福 | 民俗文化 | 奇闻趣事
建站知识 | 人世百态 | 网站导航 | 传统节日 | 搜索热点 | 星座运势 | 趣闻轶事 | 祝福的话 | 短信大全
© 2023 QicaiSpace.Com