标题:[讨论]大家来看看,一个FORM同时传文字和图片
只看楼主
rainic
Rank: 6Rank: 6
等 级:贵宾
威 望:27
帖 子:2367
专家分:0
注 册:2005-8-9
 问题点数:0 回复次数:6 
[讨论]大家来看看,一个FORM同时传文字和图片

一个FORM同时传文件和文本数据,怎么做啊?
搞了好久都没搞成
搜索更多相关主题的帖子: FORM 文字 文本 数据 
2005-10-11 09:44
suyongtao
Rank: 16Rank: 16Rank: 16Rank: 16
等 级:版主
威 望:33
帖 子:8674
专家分:127
注 册:2004-11-6
得分:0 
呵呵,为什么搞不成呀这个不难呀,不过要加上传的组件,,

面朝大海,春暖花开!
2005-10-11 10:05
rainic
Rank: 6Rank: 6
等 级:贵宾
威 望:27
帖 子:2367
专家分:0
注 册:2005-8-9
得分:0 
请具体说一下,用FSO后就不能用request.form了
request就得不到传过来的值

2005-10-11 10:38
islet
Rank: 12Rank: 12Rank: 12
等 级:贵宾
威 望:89
帖 子:6548
专家分:0
注 册:2005-1-28
得分:0 

你慢慢研究吧! [转载] ASP无组件上传·从原理剖析到实践(上) 无组件上传一直是困扰大家的一个问题。其实原理很简单,核心就是分析字符串。但是,实际操作时,却困难重重。其中的关键问题还是大家往往对原理的剖析不够深入,或者是因为过程过于繁琐,导致bug不断。一直以来,都想做一个完善的例子,只不过想想就头痛,加上没时间(借口,呵呵 ),所以没有付诸行动。

今天就咬咬牙,给大家提供一个完整的无组件上传的例子。因为本人耐性不好,所以咱们一点一点来,分几天完成。未来的几天,我会天天更新这个文档,这个过程也是大家学习和提高的过程。

(完整的源码和示例,可以在这里找到:http://www.2yup.com/asp/attach/A0000006.zip

============================================================== 第一天:认识我们的解剖对象——数据

上传文件时,首先要知道我们得到的是什么。下面是一个上传文件的表单,我们就从他开始。 <form action="doupload.asp" method=post enctype="multipart/form-data"> file1说明:<input type=text name=file1_desc> &nbsp; file1<input type=file name=file1><br> file2说明:<input type=text name=file2_desc> &nbsp; file2<input type=file name=file2><br> <input type=submit name=upload value=upload> </form>

表单中enctype="multipart/form-data"的意思,是设置表单的MIME编码。默认情况,这个编码格式是application/x-www-form-urlencoded,不能用于文件上传;只有使用了multipart/form-data,才能完整的传递文件数据,进行下面的操作(有兴趣的朋友,可以自己试试看两者的异同。方法很简单,就是把这一句去掉)。现在,我们在表单中分别填入数据: file1的说明 D:\我的 图片\BACK046.GIF file2的说明 D:\我的 图片\BACK293.GIF

这里用了中英文、空格混排。目的是让例子更有一般性。我选的这两个图片分别是54和62字节。大图片的原理完全一样,不过小图片做例子更合适些,原理容易展现。 为了看到我们得到的数据,在doupload.asp里,有这几行代码: <% formsize=request.totalbytes formdata=request.binaryread(formsize) response.BinaryWrite(formdata) %>

很简单,作用就是打出来传过来的所有数据。如果不熟悉,你可以先研究一下request和response对象的这两个方法。

提交表单,我们在ie里面查看html源,得到: -----------------------------7d22131090458 Content-Disposition: form-data; name="file1_desc"

file1μ??μ?÷ -----------------------------7d22131090458 Content-Disposition: form-data; name="file1"; filename="D:\?òμ? í???\BACK046.GIF" Content-Type: image/gif

GIF89a‘ì?f?f3?ì???ì!ù,@?.á?o ;

-----------------------------7d22131090458 Content-Disposition: form-data; name="file2_desc"

file2μ??μ?÷ -----------------------------7d22131090458 Content-Disposition: form-data; name="file2"; filename="D:\?òμ? í???\BACK293.GIF" Content-Type: image/gif

GIF89a(‘???YYYììì!ù,(@L&#8364;?j(·"j?N(34ˉ; -----------------------------7d22131090458 Content-Disposition: form-data; name="upload"

upload -----------------------------7d22131090458--

不用怀疑,这就是你从上一个“简单”表单传过来的东西。现在想想看,怎么对付这一堆东西?是不是看上去有规律,又不知道从何下手?明天,咱们就分析一下这堆“图片”,看看怎么分离出我们要的内容。

============================================================== 第二天:分拆初步

睡了个好觉,大家脑子清醒多了吧?今天中午吃的火锅,阿森纳vs.铁哥也没看完,现在一脑子大油。。。 OK,咱们继续研究这个枯燥的问题。首先,要找出规律。看上去似乎很简单,就是用 -----------------------------7d22131090458 做分隔,这样,每一个文本单元里,都是 Content-Disposition: form-data; name="表单域的名字";

表单域的内容

而每一个文件单元里,都是 Content-Disposition: form-data; name="表单域的名字"; filename="文件全路径" Content-Type: 文件类型

文件的二进制内容

那么,是不是直接用 split(formdata,"-----------------------------7d22131090458") 就可以得到各个单元了呢?答案是否定的。首先,formdata不是字符串而是二进制串,不能用split的方法;其次,这里的7d22131090458并不固定,每次都会有变化,并不适合做分隔符。所以,应该用一个更保险的办法。想到没?很简单——就用formdata的第一行做分隔符。只要用instrb函数得到换行符的位置,然后用leftb或midb函数截取数据就行了。我们动手试试: <% '' 二进制的回车<return> bncrlf=chrB(13) & chrB(10)

'' 得到formdata formsize=request.totalbytes formdata=request.binaryread(formsize)

'' 得到分隔符 divider=leftB(formdata,clng(instrb(formdata,bncrlf))-1)

'' 看看对不对? response.BinaryWrite(divider) %>

运行。。。成功了!得到了需要的divider。注意,这里的字符串函数都是针对二进制数据操作的,所以,用的是他们的二进制版,加了“b”(binary的首字母)——instrb,leftb(以后可能还出现rightb,midb,lenb。。等等)。毕竟,formdata是用“binaryread()”得到的嘛。好了,有的分隔符,就可以得到数据了。我们从简单的开始,先拿第一个单元出来看看,目标是得到表单域名称和数据。 <% '' 这是回车<return> bncrlf=chrB(13) & chrB(10)

'' 得到数据 formsize=request.totalbytes formdata=request.binaryread(formsize)

'' 得到divider,分隔符 divider=leftB(formdata,clng(instrb(formdata,bncrlf))-1)

'' 起始位置 startpos = instrb(formdata,divider)+lenb(divider)+lenb(bncrlf) '' 终止位置,从起始位置开始到下一个divider endpos = instrb(startpos, formdata, divider)-lenb(bncrlf) part1 = midb(formdata, startpos, endpos-startpos) response.BinaryWrite(part1) %>

这一段有注释,相信大家没问题。如果对这些函数不了解,可以到http://www.2yup.com/asp/referrence/index.asp下载msdn参考看看vbscript的函数用法,对提高水平有很大帮助。 这时候得到的结果可以通过查看生成的html源的方式看到: Content-Disposition: form-data; name="file1_desc"

file1的说明

好了,离成功又进一步! 下来只要分别读取part1里name="和第一个“双引号+回车”之间的内容就可以得到表单域的名称;读取连续两个回车之后的内容就可以得到表单域的值了。下面一段顺理成章: <% '' 这就是name=" const_nameis=chrb(110)&chrb(97)&chrb(109)&chrb(101)&chrb(61)&chrb(34) '' 这是回车<return> bncrlf=chrB(13) & chrB(10)

'' 得到数据 formsize=request.totalbytes formdata=request.binaryread(formsize)

'' 得到divider,分隔符 divider=leftB(formdata,clng(instrb(formdata,bncrlf))-1)

'' 起始位置 startpos = instrb(formdata,divider)+lenb(divider)+lenb(bncrlf) '' 终止位置,从起始位置开始到下一个divider endpos = instrb(startpos, formdata, divider)-lenb(bncrlf) part1 = midb(formdata, startpos, endpos-startpos)

'' 得到表单域名称,就是<input type=sometype name=somename>里的somename。 fldname = midb(part1,_ instrb(part1, const_nameis)+lenb(const_nameis),_ instrb(part1, bncrlf)-instrb(part1,const_nameis)-lenb(const_nameis)-1) '' 得到表单域的值 fldvalue = midb(part1,_ instrb(part1, bncrlf&bncrlf)+lenb(bncrlf&bncrlf),_ lenb(part1)-instrb(part1, bncrlf&bncrlf)+lenb(bncrlf&bncrlf))

'' 检查一下?可以每次打开一个注释,分别检查。 ''response.binarywrite(fldname) ''response.binarywrite(fldvalue) %>

执行一下?呵呵,没问题啦,分别打开注释,会在IE里看到“file1_desc”和“file1的说明”。 当然,这是得到文本单元的方法,不过看看上边的原始数据就知道,得到文件单元方法可以说是基本相同,只不过: 1。需要额外得到filename=""里的值,也就是文件全路径; 2。需要额外得到Content-Type: 后边的值,也就是文件的类型。 这个工作就是体力劳动了,相信大家没问题。现在更大的精力应该放在:怎么得到所有的段落内容?想来应该是某种形式的循环,但是,具体怎么做?还有,怎么样组织得到的东西,才不显得凌乱?

呵呵,不早了,这个就是咱今天晚上要做的梦了。明天来,咱就一起解决这个问题。。。。

============================================================== 第三天:得到所有的文本单元

wake up!继续啦~~~~~ 昨天,我们已经找到了得到一个单元的信息的办法,不过,还没有到实用阶段。毕竟,想实用,还至少要: 对于文本单元,能按名称检索的内容; 对于文件单元,能按名称得到文件的具体内容、类型、全路径、以及大小等信息。 今天,我们就首先着手解决文本单元的问题。

得到内容也许不难,可是,怎么组织才能使这个过程井井有条,才能符合我们的一般习惯?我们可以从现有的知识里找答案。 大家都知道,asp有一个内置对象request,他的功能是得到用户请求的相关信息,包括表单域的值。粗看上去,他的form集合的用法和我们要实现的得到文本单元内容的功能是很近似的,我们来看看request.form的几个应用的例子:

得到表单域的值 - request.form("表单域名称")或request.form("表单域在<form></form>里的序号") 得到同名表单域的各个元素 - request.form("表单域名称")(i)或request.form("表单域在<form></form>里的序号")(i) 得到同名表单域的个数 - request.form("表单域名称").Count或request.form("表单域在<form></form>里的序号").Count

如果我们能够用ourRequest.form("name"),ourRequest.form(index),ourRequest.form("name").count,ourRequest.form(index).count这样的方式,或是与之相近的方式,不就可以很好的和request对象对应起来么?而且,因为对request对象本身的熟悉,也会降低使用我们自己方法的时候的门槛,相对于写一堆getValue(name)函数这样的方法,更不容易出错,扩展性更好更灵活,可读性也好得多。那么,我们就看看如果要实现自己的request对象,都有哪些工作要做。

首先,ourRequest应该是一个对象,有自己的属性和方法。只有这样,才可能和现有的request对象做呼应。在vbs5里面,已经可以通过Class关键字,来实现自己的类了,所以,可行性上是没有问题的,只要我们自己定义一个类,然后实例化他,就可以得到我们所需的对象; 其次,因为ourRequest.form可以用名称和序号检索,所以,应该提供比较丰富的访问方式; 第三,在表单里有多个域名称相同的时候(比如多个checkbox),应该能够得到其中的各个元素,并且可以得到总个数。所以,ourRequest.form()得到的,应该也是一个可以检索的对象,而且有Count属性。

最终,结合vbscript的语言特点,兼顾开发效率,我们决定实现这样的几个类: A。UploadRequest 这个类和request对象是对应的 属性: RawData 得到原始数据,方便检查[只读] Forms 得到一个有count属性的计数器, 可以用outRequest.Forms.Count的方式,得到文本表单域的的个数[只读] Form(index) 可以用数字或文本检索文本表单域,做用类似request.form。 他返回一个FormElement型的对象 B。FormElement 可以把它看成单个表单域的化身。通过这个类,可以得到详细的表单域信息,比如name,value等等。如果有多个value(比如checkbox的情况),还可以选择用序号索引 属性: Value 得到表单域的值。如果有多个(比如checkbox), 返回所有的,用逗号分隔[默认] Name 得到表单域的名称 Item(index) 用数字索引多个值中的某一个 Count 得到对应一个name,所拥有的value的个数。主要用于checkbox[只读] C。Counter 一个辅助类,就是为了实现outRequest.Forms.Count功能。这里写的并不好,不过考虑大家的理解方便,先暂时这样。 属性: Count 得到Count 方法: setCount 设置Count

下面,我们就来看看这几个类的实现: <% Class FormElement

'' m_开头,表示类成员变量。 Private m_dicItems

Private Sub Class_Initialize() Set m_dicItems = Server.CreateObject("Scripting.Dictionary") End Sub

'' count是咱们这个类的一个只读属性 Public Property Get Count() Count = m_dicItems.Count End Property

'' Value是一个默认属性。目的是得到值 Public Default Property Get Value() Value = Item("") End Property

'' Name是得到文本域名称。就是<input name=xxx>里的xxx Public Property Get Name() Keys = m_dicItems.Keys Name = Keys(0) Name = left(Name,instrrev(Name,"_")-1) End Property

'' Item属性用来得到重名表单域(比如checkbox)的某一个值 Public Property Get Item(index) If isNumeric(index) Then ''是数字,合法! If index > m_dicItems.Count Then err.raise 1,"IndexOutOfBound", "表单元素子集索引越界" End If Itms = m_dicItems.Items Item = Itms(index) ElseIf index = "" Then ''没给值?那就返回所有的!逗号分隔 Itms = m_dicItems.Items For i = 0 to m_dicItems.Count-1 If i = 0 Then Item = Itms(0) Else Item = Item & "," & Itms(i) End If Next Else ''给个一个不是数字的东东?出错! err.raise 2,"IllegalArgument", "非法的表单元素子集索引" End If End Property

Public Sub Add(key, item) m_dicItems.Add key, item End Sub

End Class

Class UploadRequest

Private m_dicForms Private m_bFormdata

Private Sub Class_Initialize() Set m_dicForms = Server.CreateObject("Scripting.Dictionary") Call fill() End Sub

'' 有了这个,就可以检查原始数据了 Public Property Get RawData() RawData = m_bFormdata End Property

'' 这一段丑陋的代码是为了实现outRequest.Forms.Count这个功能。 Public Property Get Forms() Set Forms = New Counter Forms.setCount(m_dicForms.Count) End Property

Public Property Get Form(index) If isNumeric(index) Then ''是数字?用数字来检索 If index > m_dicForms.Count Then err.raise 1,"IndexOutOfBound", "表单元素索引越界" End If Items = m_dicForms.Items Set Form = Items(index) ElseIf VarType(index) = 8 Then ''字符串?也行! If m_dicForms.Exists(index) Then ''存在,就返回值 Set Form = m_dicForms.Item(index) Else ''不存在,就给个空值——request对象就是这么做的。 Exit Property End If Else ''给了一个不是数字也不是字符串的东东?出错! err.raise 2,"IllegalArgument", "非法的表单元素索引" End If End Property

Private Sub fill '' 得到数据 m_bFormdata=request.binaryread(request.totalbytes) '' 调用这个函数实现递归循环,读取文本单元 Call fillEveryFirstPart(m_bFormdata) End Sub

Private Sub fillEveryFirstPart(data) '' 这就是name=" const_nameis=chrb(110)&chrb(97)&chrb(109)&chrb(101)&chrb(61)&chrb(34) '' 这就是filename=" const_filenameis=chrb(102)&chrb(105)&chrb(108)&chrb(101)&_ chrb(110)&chrb(97)&chrb(109)&chrb(101)&chrb(61)&chrb(34) '' 这是回车<return> bncrlf=chrb(13) & chrb(10) '' 得到divider,分隔符 divider=leftb(data,instrb(data,bncrlf)-1) '' 起始位置 startpos = instrb(data,divider)+lenb(divider)+lenb(bncrlf) '' 终止位置,从起始位置开始到下一个divider endpos = instrb(startpos, data, divider)-lenb(bncrlf) If endpos < 1 Then ''没有下一个了!结束! Exit Sub End If part1 = midb(data, startpos, endpos-startpos) '' 得到part1的第一行 firstline = midb(part1, 1, instrb(part1, bncrlf)-1)

''没有filename=",有name=",说明是一个文本单元(这里有一个BUG,自己研究一下?当作业吧) If Not instrb(firstline, const_filenameis) > 0_ And instrb(firstline, const_nameis) > 0 Then '' 得到表单域名称,就是<input type=sometype name=somename>里的somename。 fldname = B2S(midb(part1,_ instrb(part1, const_nameis)+lenb(const_nameis),_ instrb(part1, bncrlf)_ -instrb(part1, const_nameis)-lenb(const_nameis)-1)) '' 得到表单域的值 fldvalue = B2S(midb(part1,_ instrb(part1, bncrlf&bncrlf)+lenb(bncrlf&bncrlf),_ lenb(part1)-instrb(part1, bncrlf&bncrlf)+lenb(bncrlf&bncrlf))) If m_dicForms.Exists(fldname) Then Set fElement = m_dicForms.Item(fldname) m_dicForms.Remove fldname Else Set fElement = new FormElement End If

fElement.Add fldname&"_"&fElement.Count, fldvalue m_dicForms.Add fldname, fElement

End If

'' 截取剩下的部分,递归调用这个函数,来得到下一个part1。 Call fillEveryFirstPart(rightb(data, lenb(data)-endpos-1)) End Sub

'' 这是一个公用函数,作用是二进制和字符串的转换 Private Function B2S(bstr) If not IsNull(bstr) Then for i = 0 to lenb(bstr) - 1 bchr = midb(bstr,i+1,1) If ascb(bchr) > 127 Then ''遇到了双字节,就得两个字符一起处理 temp = temp & chr(ascw(midb(bstr, i+2, 1) & bchr)) i = i+1 Else temp = temp & chr(ascb(bchr)) End If next End If B2S = temp End Function

End Class

'' 这是一个辅助类,为了实现outRequest.Forms.Count功能。 Class Counter Private m_icnt

'' count是咱们这个类的一个只读属性 Public Property Get Count() Count = m_icnt End Property

Public Function setCount(cnt) m_icnt = cnt End Function End Class %>

<% ''下面是测试码 set outRequest = new UploadRequest %>

<%=outRequest.Form(0).Name%>:<%=outRequest.Form("file1_desc")%><br> <%=outRequest.Form(1).Name%>:<%=outRequest.Form("file2_desc")%><br> <%=outRequest.Form(2).Name%>:<%=outRequest.Form(2).Count%><br> <%=outRequest.Form(3).Name%>:<%=outRequest.Form(3)%><hr>

一共有<%=outRequest.Forms.Count%>个文本单元

这里的注释很详细,而且,每一个类的属性和方法都很少,所以相信基础好的朋友读懂是没有问题的。对应的,我们的测试表单也改成了: <form action="doupload.asp" method=post enctype="multipart/form-data"> file1说明:<input type=text name=file1_desc> &nbsp; file1<input type=file name=file1><br> file2说明:<input type=text name=file2_desc> &nbsp; file2<input type=file name=file2><br> <input type=checkbox name=chk value=a>a <input type=checkbox name=chk value=b>b <input type=checkbox name=chk value=c>c <input type=checkbox name=chk value=d>d <input type=checkbox name=chk value=e>e<hr> <input type=submit name=upload value=upload> </form>

注意,这里的每一个文本表单域都要填上,因为测试码给得很特殊,读了0,1,2,3各个项目的值,测试了各个属性。不过,现实情况下,因为事先知道表单域的名称;即使不知道,也可以用outRequest.Forms.Count来循环读取,所以是没问题的,不容易出错。

现在,试试看!怎么样?成功了吧 呵呵,中英文都没有问题,用法也很简单,很清晰。现在,我们就可以说基本上解决了文本域的读取问题。

-------------------------------------------------------- 今天这一段是很有挑战性的。我写了两个多小时。对于尚处于初级的朋友,可能会觉得有些吃力。其实,关键在于深刻的理解类的概念,如果这一点没有问题,那么,理解这些代码就不在话下了。对了,今天的代码里有一个比较明显的BUG(我故意放的,当然,肯定还有不少不明显的BUG ),有兴趣的朋友可以当做作业来检验一下自己的水平。 因为今天要掌握的内容比较多,所以,明天暂停一天,给大家一个消化的机会(我也顺便偷个懒)。。。如果有疑问,请用下面的“我要提问”连接提出。 现在轻松啦,可以上床虎虎了。。。

2005-10-11 12:11
hxfly
Rank: 5Rank: 5
等 级:贵宾
威 望:17
帖 子:5807
专家分:108
注 册:2005-4-7
得分:0 

2分钟轻松搞定
呵呵

2005-10-11 12:40
84056686
Rank: 1
等 级:新手上路
帖 子:71
专家分:0
注 册:2005-10-11
得分:0 

上传文件: <form action="save.asp" method=post name=Frm onSubmit="return check_input()" enctype="multipart/form-data"> <table align="center" width="70%"> <tr> <td width="100%" colspan="2" align="center"><h4><br> <div id="Layer2">图片上传 </div> <br> </h4></td> </tr> <tr> <td width="30%" align="right">图片标题</td> <td width="70%" align="left" ><input onfocus="this.value=''" type="text" name="title" value="输入标题"> <font color="#FF0000">*</font> </td> </tr> <tr> <td width="30%" align="right">选择类型</td> <td width="70%" align="left" > <select name="types" size="1"> <option value="">选择类型</option> <option value="人物">人物</option> <option value="风景">风景</option> </select> <font color="#FF0000">默认(其他)</font> </td> </tr> <tr> <td width="30%" align="right">图片说明</td> <td width="70%" align="left" valign="middle" > <textarea name="content" cols="46" rows="7"></textarea> <font color="#FF0000">*</font> </td> </tr> <tr> <tr> <td width="30%" align="right">选择图片<font color="#FF0000">(小于1M)</font></td> <td width="70%" align="left"><input name="photo" type="FILE" style="width:300" > </td> </tr> <tr> <td width="100%" colspan="2" align="center"> <input type="submit" name="upsub" value="提交"> &nbsp;&nbsp;&nbsp;&nbsp; <input name="upsub" type="reset" value="取消"> </td> </tr> </table> 保存文件 <!--#include file="fupload.inc"--> if Request.ServerVariables("REQUEST_METHOD") = "POST" then on error resume next Dim Fields dim flag_a UploadSizeLimit=1024*1024*5 Set Fields = GetUpload() if err then response.Write("<script language='javascript'>alert('上传图片的大小或格式不符合要求,请修改后重新上传。!!');location.href = 'up.asp';</script>") end if dim Field

For Each Field In Fields.Items select case Field.name case "types" types=BinaryToString(Field.value) case "title" title=BinaryToString(Field.value) case "content" content=BinaryToString(Field.value) case "photo" filename=field.FileName fileContentType=field.ContentType filevalue=field.value end select next if filename<>"" and fileContentType<>"image/gif" and fileContentType<>"image/pjpeg" then response.write "<script>alert('上传的照片应该为GIF或JPG文件!!');history.go(-1);</script>" else if Fields("photo").Length<=0 then response.write "<script language='javascript'>alert('图片大小不能小于0K!!');history.go(-1);</script>" response.end else if Fields("photo").Length>(1024*1024) then response.write "<script language='javascript'>alert('只允许小于1M的图片上传!!');history.go(-1);</script>" response.end else 保存相应字段 end if end if end if end if 转换文件(fupload.inc) <SCRIPT RUNAT=SERVER LANGUAGE=VBSCRIPT> '限制上传图片大小 Dim UploadSizeLimit

'********************************** 得到上传数据 ********************************** Function GetUpload() Dim Result Set Result = Nothing If Request.ServerVariables("REQUEST_METHOD") = "POST" Then 'Request method must be "POST" Dim CT, PosB, Boundary, Length, PosE CT = Request.ServerVariables("HTTP_Content_Type") 'reads Content-Type header If LCase(Left(CT, 19)) = "multipart/form-data" Then 'Content-Type header must be "multipart/form-data" 'This is upload request. 'Get the boundary and length from Content-Type header PosB = InStr(LCase(CT), "boundary=") 'Finds boundary If PosB > 0 Then Boundary = Mid(CT, PosB + 9) 'Separetes boundary Length = CLng(Request.ServerVariables("HTTP_Content_Length")) 'Get Content-Length header if "" & UploadSizeLimit<>"" then UploadSizeLimit = clng(UploadSizeLimit) if Length > UploadSizeLimit then ' on error resume next 'Clears the input buffer ' response.AddHeader "Connection", "Close" ' on error goto 0 Request.BinaryRead(Length) Err.Raise 2, "GetUpload", "Upload size " & FormatNumber(Length,0) & "B exceeds limit of " & FormatNumber(UploadSizeLimit,0) & "B" exit function end if end if

If Length > 0 And Boundary <> "" Then 'Are there required informations about upload ? Boundary = "--" & Boundary Dim Head, Binary Binary = Request.BinaryRead(Length) 'Reads binary data from client

'Retrieves the upload fields from binary data Set Result = SeparateFields(Binary, Boundary) Binary = Empty 'Clear variables Else Err.Raise 10, "GetUpload", "Zero length request ." End If Else Err.Raise 11, "GetUpload", "No file sent." End If Else Err.Raise 1, "GetUpload", "Bad request method." End If Set GetUpload = Result End Function

Function SeparateFields(Binary, Boundary) Dim PosOpenBoundary, PosCloseBoundary, PosEndOfHeader, isLastBoundary Dim Fields Boundary = StringToBinary(Boundary)

PosOpenBoundary = InstrB(Binary, Boundary) PosCloseBoundary = InstrB(PosOpenBoundary + LenB(Boundary), Binary, Boundary, 0)

Set Fields = CreateObject("Scripting.Dictionary")

Do While (PosOpenBoundary > 0 And PosCloseBoundary > 0 And Not isLastBoundary) 'Header and file/source field data Dim HeaderContent, FieldContent 'Header fields Dim Content_Disposition, FormFieldName, SourceFileName, Content_Type 'Helping variables Dim Field, TwoCharsAfterEndBoundary 'Get end of header PosEndOfHeader = InstrB(PosOpenBoundary + Len(Boundary), Binary, StringToBinary(vbCrLf + vbCrLf))

'Separates field header HeaderContent = MidB(Binary, PosOpenBoundary + LenB(Boundary) + 2, PosEndOfHeader - PosOpenBoundary - LenB(Boundary) - 2)

'Separates field content FieldContent = MidB(Binary, (PosEndOfHeader + 4), PosCloseBoundary - (PosEndOfHeader + 4) - 2)

'Separates header fields from header GetHeadFields BinaryToString(HeaderContent), Content_Disposition, FormFieldName, SourceFileName, Content_Type

'Create one field and assign parameters Set Field = CreateUploadField() Field.Name = FormFieldName Field.ContentDisposition = Content_Disposition Field.FilePath = SourceFileName Field.FileName = GetFileName(SourceFileName) Field.ContentType = Content_Type Field.Value = FieldContent Field.Length = LenB(FieldContent)

Fields.Add FormFieldName, Field

'Is this ending boundary ? TwoCharsAfterEndBoundary = BinaryToString(MidB(Binary, PosCloseBoundary + LenB(Boundary), 2)) 'Binary.Mid(PosCloseBoundary + Len(Boundary), 2).String isLastBoundary = TwoCharsAfterEndBoundary = "--" If Not isLastBoundary Then 'This is not ending boundary - go to next form field. PosOpenBoundary = PosCloseBoundary PosCloseBoundary = InStrB(PosOpenBoundary + LenB(Boundary), Binary, Boundary ) End If Loop Set SeparateFields = Fields End Function

'********************************** Utilities ********************************** Function BinaryToString(str) strto = "" for i=1 to lenb(str) if AscB(MidB(str, i, 1)) > 127 then strto = strto & chr(Ascb(MidB(str, i, 1))*256+Ascb(MidB(str, i+1, 1))) i = i + 1 else strto = strto & Chr(AscB(MidB(str, i, 1))) end if next BinaryToString=strto End Function

Function StringToBinary(String) Dim I, B For I=1 to len(String) B = B & ChrB(Asc(Mid(String,I,1))) Next StringToBinary = B End Function

'Separates header fields from upload header Function GetHeadFields(ByVal Head, Content_Disposition, Name, FileName, Content_Type) Content_Disposition = LTrim(SeparateField(Head, "content-disposition:", ";")) Name = (SeparateField(Head, "name=", ";")) 'ltrim If Left(Name, 1) = """" Then Name = Mid(Name, 2, Len(Name) - 2) FileName = (SeparateField(Head, "filename=", ";")) 'ltrim If Left(FileName, 1) = """" Then FileName = Mid(FileName, 2, Len(FileName) - 2) Content_Type = LTrim(SeparateField(Head, "content-type:", ";")) End Function

'Separets one filed between sStart and sEnd Function SeparateField(From, ByVal sStart, ByVal sEnd) Dim PosB, PosE, sFrom sFrom = LCase(From) PosB = InStr(sFrom, sStart) If PosB > 0 Then PosB = PosB + Len(sStart) PosE = InStr(PosB, sFrom, sEnd) If PosE = 0 Then PosE = InStr(PosB, sFrom, vbCrLf) If PosE = 0 Then PosE = Len(sFrom) + 1 SeparateField = Mid(From, PosB, PosE - PosB) Else SeparateField = Empty End If End Function

'Separetes file name from the full path of file Function GetFileName(FullPath) Dim Pos, PosF PosF = 0 For Pos = Len(FullPath) To 1 Step -1 Select Case Mid(FullPath, Pos, 1) Case "/", "\": PosF = Pos + 1: Pos = 0 End Select Next If PosF = 0 Then PosF = 1 GetFileName = Mid(FullPath, PosF) End Function </SCRIPT> <SCRIPT RUNAT=SERVER LANGUAGE=JSCRIPT> //The function creates Field object. function CreateUploadField(){ return new uf_Init() } function uf_Init(){ this.Name = null this.ContentDisposition = null this.FileName = null this.FilePath = null this.ContentType = null this.Value = null this.Length = null } </SCRIPT> 看看吧 应该能用


吃不到葡萄说葡萄酸。 吃到了葡萄知道葡萄真是很酸! ——(wolf)
2005-10-11 16:38
rainic
Rank: 6Rank: 6
等 级:贵宾
威 望:27
帖 子:2367
专家分:0
注 册:2005-8-9
得分:0 
谢谢~~学习ING~~
这么强啊~?~!
以后学学~
今天网速超慢~~

2005-10-11 22:03



参与讨论请移步原网站贴子:https://bbs.bccn.net/thread-29818-1-1.html




关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.941176 second(s), 9 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved