简介艾恩ASP无组件上传类AienAspUpload是一套面向ASP开发者的轻量级文件上传解决方案适合需要在传统ASP环境中快速实现表单处理与文件上传的初中级开发者。该类以简洁易懂的代码实现核心上传逻辑支持提取表单数据、上传至不同文件夹、上传同时保存到数据库、限制上传扩展名与大小以及按原文件名或时间随机命名保存等实用功能。资源包共50个文件约331KB以asp源码为主辅以png、jpg、gif等图片素材、js脚本、swf组件及pdf说明文档涵盖muti、iframe、form、single、complex、swfupload等多种上传场景示例目录结构清晰便于按需查阅与二次开发。该版本为v13.11.25 build2013.11.22修复了恶意构造上传可能导致死循环的BUG稳定性有所提升。目前已有317人学习下载适合希望深入理解ASP无组件上传原理、快速集成上传功能或排查上传异常的开发者参考使用。1. 从一次文件上传翻车说起这个无组件上传类到底能干什么去年帮一个做企业站的朋友排查问题后台传个 2MB 的产品图直接 500服务器上 IIS 日志翻出来一行Request Entity Too Large折腾半天才发现是默认请求体限制卡住了。更麻烦的是那台机器是虚拟主机装不了第三方组件连Persits.Upload这种常见方案都用不了。当时翻出来的救火方案就是今天要拆的这个艾恩ASP无组件上传类 AienAspUpload——一个纯 ASP 脚本实现、不依赖任何服务器组件、丢进目录就能跑的文件上传类。它解决的核心问题很明确在只能跑经典 ASP 的老环境里把浏览器提交的multipart/form-data请求体自己解析出来把文件落盘、把表单字段读出来全程不碰Server.CreateObject那些需要注册的 COM 组件。适合谁维护老企业站、老 OA、老教务系统的同学尤其是那种服务器权限被锁死、只能改代码不能动配置的场景。下面我按「它怎么解析、怎么调、参数怎么设、坑在哪」的顺序把这份 Asp 源码拆开讲一遍。2. 无组件上传的原理multipart 报文到底长什么样2.1 为什么不用组件反而更稳经典 ASP 里做上传主流有三条路一是用Persits.Upload、SA-FileUp这类第三方组件功能全但要注册 DLL、要服务器权限二是用FileSystemObject配合Request.BinaryRead但 FSO 只能写文本二进制文件会损坏三是纯脚本解析二进制流自己按字节切分。AienAspUpload 走的是第三条。选它的理由很实际虚拟主机、共享空间、老服务器上你往往没有注册组件的权限Server.CreateObject(Persits.Upload)直接报ActiveX 部件不能创建对象。而无组件类只依赖 ASP 内置的Request.BinaryRead、ADODB.Stream这个几乎所有 Windows 环境都有和字符串处理函数兼容性拉满。代价是性能比组件差、大文件吃内存但对几 MB 的图片、文档来说完全够用。2.2 multipart/form-data 的报文结构要理解这个类怎么工作得先看清浏览器提交的原始报文。一个带文件的上传请求body 大概长这样------WebKitFormBoundaryABC123 Content-Disposition: form-data; nametitle 产品图 ------WebKitFormBoundaryABC123 Content-Disposition: form-data; namefile1; filenamedemo.jpg Content-Type: image/jpeg 这里是 demo.jpg 的二进制字节 ------WebKitFormBoundaryABC123--关键点有三个第一每段之间用boundary分隔这个 boundary 藏在请求头Content-Type: multipart/form-data; boundaryxxx里第二文件段的头部有filename和Content-Type正文是纯二进制第三结尾的 boundary 后面多两个--。无组件类的核心工作就是拿到整个 body 的字节流按 boundary 切成若干段再对每段判断是普通字段还是文件字段文件字段把二进制部分用ADODB.Stream写出去。听起来简单但字节级操作在 VBScript 里全是坑这也是为什么很多人自己写一半就放弃。2.3 二进制流在 VBScript 里的处理方式VBScript 没有真正的字节数组类型处理二进制一般靠ADODB.Stream的Read和Write配合ChrB、AscB、LenB、MidB这些「B 系列」函数。AienAspUpload 里大量用到InStrB来定位 boundary 的字节位置用MidB截取二进制片段。这里有个血泪经验普通字符串函数和 B 系列函数绝对不能混用InStr和InStrB在含中文或二进制时结果完全不同混用会导致 boundary 定位偏移文件头尾多出或少掉几个字节图片能存下来但打不开。 读取整个请求体到内存注意 BinaryRead 的参数是字节数 Dim binData binData Request.BinaryRead(Request.TotalBytes) 从 Content-Type 头里抠出 boundary Dim contentType, boundary contentType Request.ServerVariables(HTTP_CONTENT_TYPE) 常见做法是用 InStrB 定位 boundary 再截取 boundary MidB(contentType, InStrB(1, contentType, boundary) 9)上面这段是解析的起点。Request.TotalBytes给出请求体总字节数BinaryRead一次性读进来。注意BinaryRead和Request.Form不能同时用一旦调了BinaryRead再访问Request.Form会报错这是新手最容易踩的坑之一。3. 把类跑起来调用步骤与参数配置3.1 最小可运行示例假设你已经把AienAspUpload.asp放到了站点目录页面表单这样写form actionupload.asp methodpost enctypemultipart/form-data input typetext nametitle / input typefile namefile1 / input typesubmit value上传 / /form处理页upload.asp的调用逻辑大致如下!--#include fileAienAspUpload.asp-- % Dim up, savePath, msg Set up New AienAspUpload 实例化上传类 up.MaxSize 5 * 1024 * 1024 单文件上限 5MB up.AllowedExt jpg|jpeg|png|gif|pdf|doc|docx up.SavePath Server.MapPath(/upload/) 落盘目录必须已存在且有写权限 up.SaveFileNameType 1 1时间戳命名2原文件名3自定义 If up.Upload() Then msg 上传成功 up.Form(title) 文件 up.FileName(file1) Else msg 失败 up.ErrorMsg End If Set up Nothing Response.Write msg %逻辑说明New AienAspUpload创建实例后先设参数再调Upload()。Upload()内部完成 boundary 解析、字段提取、文件落盘返回布尔值表示成败。成功后用up.Form(字段名)取普通表单值用up.FileName(文件字段名)取保存后的文件名。参数说明见下表。参数含义常见取值MaxSize单文件字节上限2MB10MB按业务定AllowedExt允许扩展名竖线分隔jpg|png|pdfSavePath物理落盘路径Server.MapPath(/upload/)SaveFileNameType命名策略1 时间戳 / 2 原名 / 3 自定义OverWrite同名是否覆盖True / False3.2 目录权限与命名策略SavePath指向的目录必须提前建好并且给 IIS 的匿名账户老系统一般是IUSR_机器名新系统是IIS_IUSRS写权限。这一步不做Upload()会返回失败但错误信息可能只写「保存失败」不告诉你权限问题排查起来很费劲。命名策略上我一般强制用时间戳SaveFileNameType 1原因有两个一是中文原文件名在某些编码下会乱码二是同名覆盖会静默丢文件。如果业务非要保留原名至少把OverWrite设成 False让重名时自动加序号。 时间戳命名的大致实现思路 Dim newName newName Year(Now) Right(0 Month(Now),2) Right(0 Day(Now),2) _ Right(0 Hour(Now),2) Right(0 Minute(Now),2) Right(0 Second(Now),2) _ . ext这段是命名逻辑的示意实际类里会封装好。要点是扩展名要从原文件名里取并且取完要再校验一次是否在 AllowedExt 白名单里不能只信前端。3.3 表单字段与文件的读取顺序有个容易被忽略的点multipart报文里字段和文件的顺序取决于表单里控件的排列顺序。AienAspUpload 解析时是按 boundary 顺序逐段处理的所以up.Form(title)能取到值的前提是那段已经被解析过。稳妥做法是先调Upload()完成全部解析再统一读字段和文件名不要在解析过程中穿插读取。另外如果表单里有多个同名文件框比如file1、file2类一般用up.FileName(file1)、up.FileName(file2)分别取。如果要做多文件上传得确认你手上这份源码是否支持数组式读取不支持的话就老老实实一个框一个字段。4. 避坑与排查那些年上传类教我的事4.1 上传成功但文件打不开现象页面提示上传成功文件名也对但下载下来图片是坏的、PDF 打不开。 原因九成是二进制截取时多切或少切了字节常见于 boundary 定位用了InStr而不是InStrB或者文件段结尾的CRLF没去掉。 解决用十六进制编辑器对比原文件和落盘文件看头部和尾部差几个字节。重点检查MidB的起止位置boundary 前后的ChrB(13) ChrB(10)必须精确剥离。4.2 大文件直接 500 或超时现象小文件正常超过 1MB 就报错或页面卡死。 原因一是 IIS 的maxRequestEntityAllowedIIS6或requestLimits maxAllowedContentLengthIIS7限制二是 ASP 脚本超时Server.ScriptTimeout默认 90 秒三是无组件类把整个文件读进内存大文件吃爆内存。 解决先改 IIS 请求体限制再在页面顶部加Server.ScriptTimeout 300。但根本上无组件类不适合传几十 MB 的大文件超过 10MB 建议换组件方案或分片。4.3 中文文件名乱码现象上传中文名文件落盘后名字变成乱码或问号。 原因浏览器提交的filename编码和服务器解析编码不一致老 IE 用 GBK现代浏览器多用 UTF-8。 解决统一用时间戳命名绕开这个问题如果必须保留原名得先判断编码再转换但 VBScript 做编码转换很别扭不推荐。4.4 权限报错但提示含糊现象Upload()返回 FalseErrorMsg只说「保存失败」。 原因SavePath目录不存在或 IIS 账户没有写权限。 解决先在服务器上手动确认目录存在再右键属性看安全选项卡里IIS_IUSRS是否有「写入」。虚拟主机的话联系空间商确认上传目录权限别自己瞎改。4.5 和 Request.Form 冲突现象调完上传类后页面其他地方的Request.Form(xxx)报错。 原因Request.BinaryRead一旦执行Request.Form集合就不可用了。 解决所有表单值都通过上传类的up.Form()读取不要再用原生Request.Form。这是设计上的硬约束不是 bug。5. 进阶技巧把上传类用得更稳的几个习惯用久了我养成了几个固定动作这里分享两个最实用的。第一个是上传前先做一次「预检」不急着落盘先判断大小和扩展名不合格直接返回省得解析完再删文件 预检在 Upload() 之前先看 Content-Length 和文件名 Dim totalSize totalSize Request.TotalBytes If totalSize 5 * 1024 * 1024 Then Response.Write 文件过大 Response.End End If 扩展名白名单二次校验防止改后缀绕过第二个是落盘后立刻校验文件头。图片有固定的魔数比如 JPG 开头是FF D8 FFPNG 是89 50 4E 47。用ADODB.Stream读前几个字节比对能挡掉一批改后缀的伪装文件 读取落盘文件的前 3 个字节做魔数校验 Dim st, head Set st Server.CreateObject(ADODB.Stream) st.Type 1 : st.Open st.LoadFromFile saveFullPath head st.Read(3) st.Close : Set st Nothing JPG 魔数 FF D8 FF转成字节比较 If AscB(MidB(head,1,1)) HFF Then 不是合法 JPG删除并报错 End If这段逻辑说明ADODB.Stream以二进制模式Type 1打开文件Read(3)读前 3 字节再用AscB取字节值比对。参数上注意LoadFromFile要传物理路径不是 URL。这个校验能挡住「把 .exe 改成 .jpg」这类低级绕过虽然不能替代杀毒但对老站来说够用。还有一个习惯是给上传目录加一层隔离上传的文件不放在 Web 根目录下直接可访问的位置而是放在根目录外通过一个下载页用ADODB.Stream读出来输出。这样即使传上来的是脚本文件也没法直接执行。老站被上传漏洞搞挂的案例太多了多这一步能省很多后悔药。从那以后我每次接手老 ASP 站的上传功能都强制走一遍「预检大小 → 白名单扩展名 → 时间戳命名 → 魔数校验 → 目录隔离」这五步哪怕业务说「就传个图而已」。希望帮到你。本文还有配套的精品资源点击获取