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>  
file1<input type=file name=file1><br>
file2说明:<input type=text name=file2_desc>  
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€?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的说明

时间: 2024-08-25 00:35:32

ASP无组件上传·从原理剖析到实践(上)的相关文章

ASP无组件上传·从原理剖析到实践(中)

上传|无组件 第五天:得到文件单元 今天我们要进行的部分,是比较有趣味性地--得到文件内容.其实,看看我们的要处理的数据,再看看前天文本单元的处理,相信大家也会心中有数. 为了清晰的区分文件和文本单元,这一次,我们用ourRequest.file(index)来对应文本单元的ourRequest.form(index).当然,因为对于文件,我们需要得到的信息不同于文本,所以这次得到的,也不会是FormElement,而是一个新对象FileElement. 文件单元和文本单元在原始数据上,不同点少

ASP无组件上传·从原理剖析到实践(下)

上传|无组件 第七天:实现附加功能 今天,我们就来实现昨天提出的方法和属性,来完善我们的文件上传类.以前没有太注意的性能问题,这一次也要彻底的解决:1.所有的变量先声明,后使用:2.设置类的teminate方法:3.简化有些地方的写法,注意细节.我们的原则,就是先实现,后优化.当然,象变量声明这样的东西,如果程序很大,最好还是在写程序的时候一次过.如果写完了才加,可以在页面开头加上option explicit(强制变量声明),然后测试所有的方法和属性,直到没有错误为止. 另外,异常代码我们也整

ASP无组件上传?从原理剖析到实践(下)

第七天:实现附加功能今天,我们就来实现昨天提出的方法和属性,来完善我们的文件上传类.以前没有太注意的性能问题,这一次也要彻底的解决:1.所有的变量先声明,后使用:2.设置类的teminate方法:3.简化有些地方的写法,注意细节.我们的原则,就是先实现,后优化.当然,象变量声明这样的东西,如果程序很大,最好还是在写程序的时候一次过.如果写完了才加,可以在页面开头加上option explicit(强制变量声明),然后测试所有的方法和属性,直到没有错误为止.另外,异常代码我们也整理一下:代码 类名

ASP无组件上传?从原理剖析到实践(中)

第五天:得到文件单元今天我们要进行的部分,是比较有趣味性地--得到文件内容.其实,看看我们的要处理的数据,再看看前天文本单元的处理,相信大家也会心中有数.为了清晰的区分文件和文本单元,这一次,我们用ourRequest.file(index)来对应文本单元的ourRequest.form(index).当然,因为对于文件,我们需要得到的信息不同于文本,所以这次得到的,也不会是FormElement,而是一个新对象FileElement.文件单元和文本单元在原始数据上,不同点少得可怜:1.第一行多

Asp无组件上传带进度条(续)

上传|无组件 几个月前,写过一篇关于Asp无组件上传带进度条的Blog,当时主要分析了一下通过Web文件上传并在后台获取分析数据的实现原理.其中实现进度条的根本就是要实现分块获取数据,根据分块大小和块数记录已上传大小.还有一些具体的细节问题当时并没有说清楚: Q: 进度信息如何访问?A: 进度信息保存在Application中,每次上传时生成一个进度ID,根据这个进度ID可以检索Application中的当前上传进度信息. Q: 进度信息以什么形式保存在Application中?A: Asp太弱

asp无组件上传算法的改进

上传|算法|无组件 前几天帮朋友faintbear修改一个"asp无组件上传"的代码,得了几点心得,写在此处,或许还有点用处. 我没有开发过asp程序,只是临时报佛脚,修改了一下控制语句,所以,这里不再给出asp代码,只是说明一下思路.(你最好在看这篇文章前先浏览一下faintbear的<asp无组件上传的原理 (转) >这篇文章,重复的部分我不再叙述了) 大体是这样的,一个form表单中可能post多个文本,居各简单的例子:<form method="po

Asp无组件上传进度条解决方案

解决|上传|无组件 一.无组件上传的原理我还是一点一点用一个实例来说明的吧,客户端HTML如下.要浏览上传附件,我们通过<input type="file">元素,但是一定要注意必须设置form的enctype属性为"multipart/form-data": <form method="post" action="upload.asp" enctype="multipart/form-data&q

Asp无组件上传进度条解决方案_应用技巧

一.无组件上传的原理我还是一点一点用一个实例来说明的吧,客户端HTML如下.要浏览上传附件,我们通过<input type="file">元素,但是一定要注意必须设置form的enctype属性为"multipart/form-data": <form method="post" action="upload.asp" enctype="multipart/form-data">&l

ASP实例:一个简单的ASP无组件上传类

简单的ASP无组件上传类,发出来让大家看看.可以做做实验! 以下为引用的内容: <%@ language="javascript"%><%var self = Request.serverVariables("SCRIPT_NAME");if (Request.serverVariables("REQUEST_METHOD")=="POST"){        var oo = new uploadFile(