巧用JS实现ASP上传组件功能

www.dgmps.com 原创 欢迎转载
htmlfile能做神马?Google用它来做长连接,我们还能用它来做ASP上传 。
下面的代码仅创建了一个htmlfile的ActiveX对象,没做文件保存。
原理是利用了recordset的appendChunk方法来连续读取上传数据,解决IIS上传默认不允许超过200kb的问题,然后使用xml分析二进制内容。
上代码吧:

<%@ language="javascript" codepage="65001" %><%
Boot();
function Boot()
{
        if(Request.QueryString("Mode").Item != "Down") return ShowForm();
        // 文件下载处理
        if(!Application("TempName")) return Response.Write("No File");
        Response.addHeader("Content-Disposition", "Attachment;filename=\"" + encodeURIComponent(Application("TempName")) + "\"");
        Response.addHeader("Content-Length", Application("TempSize"));
        Response.BinaryWrite(Application("TempFile"));
}
function ShowForm()
{ %><!doctype html><html><head>
        <meta charset="UTF-8" />
        <title>文件上传</title>
        <style type="text/css">
        body{ font: 4mm/7mm simsun }
        </style>
</head><body><%
var up = new UploadClass;
if(Request.ServerVariables("REQUEST_METHOD").Item == "POST")
{
        var str = up.ReadForm();
        if(str != "OK") Response.Write(str);
        else
        {
                var data = up.Form("test");
                if(data[0].Data) Response.Write("您提交的文本为:" + data[0] + "<br />");
                if(data[1].File)
                {
                        Response.Write("您上传的文件是:<a href=\"?Mode=Down\">" + data[1].File + "</a> (" + data[1].Size + " bytes)<br />");
                        Application("TempFile") = data[1].Data;
                        Application("TempSize") = data[1].Size;
                        Application("TempName") = data[1].File;
                }
        }
}%><form method="post" enctype="multipart/form-data">
文本:<input name="test" /><br />
文件:<input name="test" type="file" />
<input type="submit" value="上传" /><br />
当前最大允许上传 <%= up.MaxSize %> Bytes,支持的文件类型:<%= up.Filter %><%
if(Application("TempName")) Response.Write("<br />当前的临时文件为:<a href=\"?Mode=Down\">" + Application("TempName") + "</a> (" + Application("TempSize") + " Bytes)");
%>
</form></body></html><% }

/* 文件上传类,支持多文件及文字混合上传 */
function UploadClass()
{
        this.MaxSize = 512 * 1024;
        this.Filter = "jpg|png|gif|bmp|doc|docx|txt|zip|rar";
        var data = new Object;        // 存储表单对象
        this.ReadForm = function()
        {
                var nmbTotal = Request.TotalBytes;
                if(nmbTotal > this.MaxSize) return "文件大小超过限制。";
                var strRule = Request.ServerVariables("Http_Content_Type").Item || "";
                strRule = (strRule.match(/boundary=(.+)/) || [])[1];
                if(!strRule) return "非文件上传表单";
                strRule = "2d2d" + strRule.replace(/[\w\-]/g, function($1){ return $1.charCodeAt(0).toString(16); });
                var xml = new ActiveXObject("htmlfile").createElement("xml");
                var root = xml.createElement("root"); root.dataType = "bin.hex";
                var rcd = xml.recordset; rcd.fields.append("bin", 205, -1);
                rcd.open(); rcd.addNew();
                var nmbByte = 0, nmbRead = 200000;        // 缓冲区大小
                while(Response.IsClientConnected() && nmbByte < nmbTotal)
                {
                        rcd(0).appendChunk(Request.BinaryRead(nmbRead));
                        nmbByte += nmbRead;
                }
                root.nodeTypedValue = rcd(0).value; rcd.close();
                var arr = root.text.split(strRule); arr.shift(); arr.pop();
                var reg = new RegExp("\\.(?:" + this.Filter + ")$", "i");
                for(var i = 0; i < arr.length; i++)
                {
                        var nmbSplit = arr[i].indexOf("0d0a0d0a");
                        // 此处仅支持UTF-8解码,gbk请借助rcd或流对象
                        var strHead = arr[i].slice(4, nmbSplit).replace(/(\w{2})/g, "%$1");
                        strHead = decodeURIComponent(strHead);
                        var strPath = (strHead.match(/filename="(.+?)"/i) || [])[1] || "";
                        strPath = (strPath.match(/([^\\\/]+)$/) || [])[1];
                        if(strPath && !reg.test(strPath)) return "不允许的文件类型。";
                        // 查找两个空行,忽略最后一个空行
                        root.text = arr[i].slice(nmbSplit + 8, -4);
                        var field = (strHead.match(/name="(.+?)"/i) || [])[1] || "";
                        if(!data[field]) data[field] = new Array;
                        data[field].push(
                        {
                                File : strPath, Size : root.text.length / 2,
                                Data : strPath ? root.nodeTypedValue : decodeURIComponent(root.text.replace(/(\w{2})/g, "%$1")),
                                toString : function(){ return this.Data; }
                        });
                }
                return "OK";
        }
        this.Form = function(strField)
        {
                var item = data[strField] || [];
                return item.length < 2 ? item[0] : item;
        }
} %>