怎样无组件上传文件?

示例网页:无组件上传文件

源代码:点击下载

本文提供了一个无组件上传文件的解决方案。它由5个文件组成。

  1. UploadFile.asp,上传文件的前台页面,供用户选择要上传的文件。
  2. UploadFile_Process.asp,后台过渡文件,可以在这里做一些个性化的设置,如上传到哪个文件夹等等。
  3. CBeanFile.asp,用来做一些验证工作,如果通过验证就上传文件到指定目的地(通过调用下面的两个文件)。
  4. CFile.asp,文件类,存储上传的文件数据,如文件名等等,它有一个方法用来将文件数据保存到指定的文件夹。
  5. CFormDataGetter.asp,表单数据获取类,这是上传文件的核心程序,对提交的表单进行分析,并取出文件数据。

下面分别来建立这5个文件,然后访问Upload.asp就可以运行了(假设这5个文件都放在你的本地服务器的Example文件下,那么只需在浏览器地址栏里输入http://localhost/Upload/UploadFile.asp就可以访问)。虽然这个过程需要写比较长的代码,但是好在它们已经写好了,你可以只需要复制粘贴即可,当然,在应用到你自己的网站时,需要进行一些个性化的改造,但这些改造非常简单,因为核心程序可以方便地移植,不用做任何修改。

虽然源代码就在下面,但是你现在可能不想细看,而且还懒得复制粘贴,那么有一个好消息,可以直接下载源代码,部署到自己的网站中就可以正常工作了。嗯,先让它工作起来,再来做个性化的修改,比先看懂代码再粘贴,的确是个更不错的思路。

一、UploadFile.asp,基本就是一个HTML文件

<%@LANGUAGE="VBSCRIPT" CODEPAGE="65001"%>
<% Option Explicit %>
<%Session.CodePage=65001%>
<%
    ' 此函数用来显示一些提示信息。
    ' 当上传之后,你可以将一些反馈信息(如成功还是失败等)
    ' 放在Session变量里,然后在相应的页面中将信息显示出来。
    ' 以下两个函数正是用来做这件事
    Function ShowInfo()
        ShowInfo = ShowInfoFrom("ssnInfo", True)
    End Function

    Public Function ShowInfoFrom(ByRef sSessionName, ByVal bDelete)
        Dim s, i, aInfo, ll, lu, sT
        
        On Error Resume Next
            aInfo = Session(sSessionName)
            If Err.Number <> 0 Then
                ShowInfo = ""
                Exit Function
            End If
            
            ll = LBound(aInfo)
            If Err.Number = 0 Then
                lu = UBound(aInfo)
                For i = ll to lu
                    sT = aInfo(i)
                    If Len(sT) > 0 Then
                        s = s & "
  • " & sT & "
  • " End If Next If Len(s) > 0 Then s = "
      " & s & "
    " End If Else s = aInfo End If On Error Goto 0 IF Len(s) > 0 Then s = "
    " & s & "
    " End If ShowInfoFrom = s If bDelete Then Session(sSessionName) = "" End Function %> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <style type="text/css"> form label { width: 3em; display: inline-block; } #idUploadInfo { display: none; } </style> <script type="text/javascript"> var oImg = new Image(); oImg.src = "wait.gif"; function upload() { document.getElementById('idUpload').style.display = 'none'; document.getElementById('idUploadInfo').style.display = 'block'; } </script> <title>无组件上传文件示例</title> </head> <body> <div id="idInfo"><%= ShowInfo %></div> <form name="fmUpload" action="UploadFile_Process.asp" method="post" enctype="multipart/form-data"> <div id="idUpload"> <p><label for="idFile">文件:</label><input type="file" name="File" /></p> <p><label for="idSubmit"></label><input type="submit" name="submit" onclick="upload();" /></p> </div> <div id="idUploadInfo"> <img src="wait.gif" alt="正在上传……" /> <p>正在上传……</p> </div> <p>可以上传的文件类型:.jpg, .bmp, .gif</p> <p>文件大小限制:1.5兆</p> <p>(以上限制可以在后台修改。)</p> </form> </body> </html>

    二、UploadFile_Process.asp

    <%@LANGUAGE="VBSCRIPT" CODEPAGE="65001"%>
    <% Option Explicit %>
    <%Session.CodePage=65001%>
    <html-->
    <!--#include file="CBeanFile.asp"-->
    <head>
        <title>上传文件处理</title>
        <style type="text/css">
        <!--
        -->
        </style>
        <script type="text/javascript">
        <!--
        //-->
        </script>
    </head>
    <body>
        <div id="divWrapWrap">
            <div id="divWrap">
                <div id="divWrap_Content">
                    <div class="doodleBox">
                        <div class="header"><strong>上传文件处理</strong></div>
                        <div class="body">
                        <%              
                            AvoidDuplicateSubmit_Lock          ' 防止多次提交
                            Dim bean
                            Set bean = New CBeanFileForExample
                            If bean.validate() Then
                                ' 如果通过验证,bean文件会自己处理上传的过程,这里什么也不用做,当然你可以添加一些
                                ' 自定义消息,如上传成功之类的提示信息在这里。实际上bean连这种提示信息也做好了。
                            Else
                                ' 如果没有通过验证呢?实际上bean文件也做了相应的处理,你也可以在这里什么都不做
                                Response.Write("没有选择文件")
                            End If
                            
                            Set bean = Nothing
                        %>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </body>
    </html>
    <%
        ' 返回到前一页
        Response.Redirect Request.ServerVariables("HTTP_REFERER")
        
        '
        ' 防止多次重复提交相同的数据
        '
        Function AvoidDuplicateSubmit_Lock()
            Session("ssnlPostCount") = Clng(Session("ssnlPostCount")) + 1
            
            If Session("ssnlPostCount") > 1 Then
                Session("errors") = "您已经提交过了"
                Session("ssnlPostCount") = 0
                Response.Write(Session("errors"))
                Response.Write("<a href='" & Request.ServerVariables("HTTP_REFERER") & "'>返回</a>")
                Response.End
            End If
            
            AvoidDuplicateSubmit_Unlock
        End Function
        
        '
        ' 防止多次重复提交相同的数据
        '
        Function AvoidDuplicateSubmit_Unlock()
            Session("ssnlPostCount") = 0
        End Function
    %>
    

    三、CBeanFile.asp 文件

    <!--#include file="CFormDataGetter.asp"-->
    <%
        Class CBeanFileForExample
            Private oForm
            Private oFile
            ' 文件大小限制
            Private lSizeLimited
            ' 文件上传到哪个文件夹下?
            Private sPathForUpload
            ' 文件保存到数据库的哪个表中?
            Private sTableRecordsUpload
            Private sUserName
            ' 缩略图的宽度与高度的最大值的限制
            Private lThumbnailDimentionSizeLimit
            
            Private Function bValidateExp(ByRef sPattern, ByRef s)
                Dim regEx
                Set regEx = Server.CreateObject("VBScript.RegExp")
                regEx.Global = True
                regEx.IgnoreCase = True
                regEx.Pattern = sPattern
                bValidateExp = regEx.Test(s)
                Set regEx = Nothing
            End Function 
            
            Private Sub Class_Initialize()
                Set oForm = New CFormDataGetter
                Set oFile = New CFile
                ' 限定文件大小为1.5兆
                Me.SizeLimited = (1024 * 1024) * 1.5
                Me.PathForUpload = "Upload"
                Me.TableRecordsUpload = "MF_Gallery"
                Me.UserName = ""
                Me.LogPath = ""
                Me.LogFileName = "DataRead.xml"
                Me.ThumbnailDimentionSizeLimit = 200
                Me.GetRequest
            End Sub
            
            Private Sub Class_Terminate()
                Set oForm = Nothing
                Set oFile = Nothing
            End Sub
            
            Public Sub GetRequest()
                Set oFile = oForm.GetFile("File")
            End Sub
            
            Public Function Validate()
                Validate = True
                If Me.Form.FormSize <= 0 Then
                    AddInfo("没有选择文件")
                    Validate = False
                Else                        
                    If Me.File Is Nothing Then
                        AddInfo("上传文件出现未知错误,请确认上传方式是否正确 (请检查<form></form>元素的 enctype 属性设置)")
                        Validate = False
                    Else
                        If Me.File.Size <= 0 Then 
                            AddInfo("没有选择文件或者文件大小为 0 字节")
                            Validate = False
                        End If
                    End If
                End If 
                
                If Validate Then
                    ' 开始对上传的文件进行分析
                    Dim bnsFileFlag, sFileType
                    bnsFileFlag = LeftB(Me.File.BinaryStream, 3)
                    
                    ' 对文件类型进行检测
                    Select Case Me.Form.ConvertBinaryToString(bnsFileFlag)
                        Case "GIF"
                        Case Else
                            Select Case LeftB(bnsFileFlag, 2)
                                Case Me.Form.ConvertStringToBinary("BM"), Me.Form.ConvertStringToBinary("BA"), Me.Form.ConvertStringToBinary("CI"), Me.Form.ConvertStringToBinary("CP"), Me.Form.ConvertStringToBinary("IC"), Me.Form.ConvertStringToBinary("PT")
                                    
                                Case ChrB(&HFF) & ChrB(&HD8)
                                    ' 有可能是JPEG格式文件
                                Case Else
                                    AddInfo "目前不支持此文件( " & Me.File.Name & " )的类型,不能上传"
                                    Validate = False
                            End Select
                    End Select
                End If
                
                ' 检测文件大小是否超限
                If Validate Then
                    If Me.File.Size > Me.SizeLimited Then
                        AddInfo "目前最大只能上传大小为 " & Me.SuitableUnit(Me.SizeLimited) & " 的文件,而你选择的文件( " & Me.File.Name & " )的大小为 " & Me.SuitableUnit(Me.File.Size) & ",超出了限制"
                        Validate = False
                    End If
                End If
                
                If Validate Then
                    ' 通过所有的检测,开始上传                
                    ' 检测指定的上传路径是否存在
                    Dim oFSTest
                    Set oFSTest = Server.CreateObject("Scripting.FileSystemObject")
                    If Not oFSTest.FolderExists(Server.MapPath(Me.PathForUpload)) Then
                        ' 如果不存在则创建一个
                        oFSTest.CreateFolder(Server.MapPath(Me.PathForUpload)) 
                    End if
                    Set oFSTest = Nothing
                    ' 上传目的地路径
                    Dim sPermanentLink, oMF, sSQL, sState, oDB
                    sState = Me.File.Save(Server.MapPath(Me.PathForUpload) & "\" & Me.File.Name, 2)
                    If sState = "OK" Then
                            AddInfo("上传文件成功,文件链接地址为:<a href=""" & Me.PathForUpload & "/" & Me.File.Name & """ target=""_blank"" title=""点击查看"">" & Me.PathForUpload & "/" & Me.File.Name & "</a>")
                    Else
                        AddInfo sState
                        Validate = False
                    End If
                End IF
            End Function
            
            Public Property Get Form()
                Set Form = oForm
            End Property
            
            Public Property Let Form(ByRef o)
                Set oForm = o
            End Property
            
            Public Property Get File()
                Set File = oFile
            End Property
            
            Public Property Let File(ByRef o)
                Set oFile = o
            End Property
            
            Public Property Get SizeLimited()
                SizeLimited = lSizeLimited
            End Property
            
            Public Property Let SizeLimited(ByVal l) 
                lSizeLimited = l
            End Property
            
            Public Property Get PathForUpload()
                PathForUpload = sPathForUpload
            End Property
            
            Public Property Let PathForUpload(ByRef s)
                sPathForUpload = s
            End Property
            
            Public Property Get TableRecordsUpload()
                TableRecordsUpload = sTableRecordsUpload
            End Property
            
            Public Property Let TableRecordsUpload(ByRef s) 
                sTableRecordsUpload = s
            End Property
            
            Public Property Get UserName()
                UserName = sUserName
            End Property
            
            Public Property Let UserName(ByRef s)
                sUserName = s
            End Property
            
            Public Property Get LogPath()
                ON Error Resume Next
                LogPath = Session("ssnLogPath")
                If Err.number <> 0 Then
                    LogPath = ""
                End If
                On Error Goto 0
            End Property
            
            Public Property Let LogPath(ByRef s)
                Session("ssnLogPath") = s
            End Property
            
            Public Property Get LogFileName()
                On Error Resume Next
                LogFileName = Session("ssnLogFileName")
                If Err.number <> 0 then
                    LogFileName = "DataReadLog.xml"
                end If
                On Error Goto 0
            End Property
            
            Public Property Let LogFileName(ByRef s)
                Session("ssnLogFileName") = s
            End Property
            
            Public Property Get ThumbnailDimentionSizeLimit()
                ThumbnailDimentionSizeLimit = lThumbnailDimentionSizeLimit
            End Property
            
            Public Property Let ThumbnailDimentionSizeLimit(ByVal l)
                lThumbnailDimentionSizeLimit = l
            End Property
            
            '
            ' 将以字节为单位的数字转换成合适单位的值
            '
            Public Function SuitableUnit(ByVal lB)
                Dim i, lVal, aUnit
                
                aUnit = Array("B", "KB", "MB", "GB", "TB")
                lVal = Abs(lB)
                i = 0
                While lVal >= 1024 And i < UBound(aUnit)
                    i = i + 1
                    lVal = lVal / 1024
                Wend
                
                SuitableUnit = Sgn(lB) * Round(lVal, 2) & " " & aUnit(i)
            End Function
    
            ' 添加信息
            Public Function AddInfo(ByRef s)
                AddInfo2 s, "ssnInfo"
            End Function
            
            ' 添加信息到
            Public Function AddInfo2(ByRef s, ByRef sSessionName)
                Dim aInfo, ll, lu
                
                If Len(s) <= 0 Then
                    Exit Function
                End If
                
                On Error Resume Next
                    aInfo = Session(sSessionName)
                    If Err.Number <> 0 Then
                        aInfo = ""
                    End If
                    
                    Err.Clear
                    
                    '测试已有信息是否是数组
                    ll = LBound(aInfo)
                    If Err.Number <> 0 Then
                        ' 不是数组
                        If Len(aInfo) > 0 Then
                            aInfo = Array(aInfo, s)
                        Else
                            aInfo = s
                        End If
                    Else
                        ' 是数组
                        lu = UBound(aInfo)
                        Redim Preserve aInfo(lu + 1)
                        aInfo(lu+1) = s
                    End If
                On Error Goto 0
                Session(sSessionName) = aInfo
            End Function
        End Class
    %>
    

    四、CFile.asp 文件

    <% 
    '**************************************************** 
    '文件名: CFile.asp
    '描  述:文件类
    '	
    '
    '**************************************************** 
    
    '# *Using CFormDataGetter.asp*
    
    Class CFile
        ' 完整的路径名+文件名+后缀名
        Private sFullName
        Private sDescription
        Private sMIME
        Private bnsContent
        Private csClass
        
        Private Sub Class_Initialize()
            csClass = "CFile"
        End Sub
        
        Public Property Get FullName()
            FullName = sFullName
        End Property
        
        Public Property Let FullName(ByRef sNewFullName) 
            sFullName = sNewFullName
        End Property
        
        ' 获取文件的路径,不含文件名
        Public Property Get Path()
            Path = Left(sFullName, InStrRev(sFullName, "\"))
        End Property
        
        ' 去掉路径的文件名+后缀名
        Public Property Get Name()
            Name = Right(sFullName, Len(sFullName) - InStrRev(sFullName, "\"))
        End Property
        
        ' 去掉路径后的文件名 (不要后缀名)
        Public Property Get ShortName()
            Dim i
            
            i = InStrRev(Me.Name, ".")
            If i > 0 Then
                ShortName = Left(Me.Name, InStrRev(Me.Name, ".") - 1)
            Else
                ShortName = Me.Name
            End If
        End Property
        
        Public Property Let Description(ByRef sNewDesc)
            sDescription = sNewDesc
        End Property
        
        Public Property Get Description()
            Description = sDescription
        End Property
        
        Public Property Let MIME(ByRef sNewMIME)
            sMIME = sNewMIME
        End Property
        
        Public Property Get MIME()
            MIME = sMIME
        End Property
        
        Public Property Get Size()
            Size = LenB(Me.BinaryStream)
        End Property
        
        '
        ' 设置文件的二进制流
        '
        Public Property Let BinaryStream(ByRef bnsNewBinaryStream)
            bnsContent = bnsNewBinaryStream
        End Property
        
        '
        ' 获取文件的文本
        '
        Public Property Get TextStream(ByRef sCharset)
            Dim stm
            
            Set stm = Server.CreateObject("ADODB.Stream")
            stm.Type = 2
            stm.Open
            stm.WriteText bnsContent
            stm.Position = 0
            If Len(sCharset) > 0 Then stm.Charset = sCharset
            TextStream = stm.ReadText
            stm.Close
            Set stm = Nothing
        End Property 
        
        '
        ' 获取文件的二进制流
        '
        Public Property Get BinaryStream()
            BinaryStream = bnsContent
        End Property
        
        ' 后缀名
        Public Property Get Ext()
            Ext = Right(Me.Name, Len(Me.Name) - InStrRev(Me.Name, "."))
        End Property
        
        Private Sub CFile_Initialize()
            sFullName = ""
            sDescription = ""
            sMIME = ""
            bnsContent = ChrB(0)
        End Sub
        
        '
        ' 打开文件
        '
        Public Function Open(ByRef sFullName)
            Dim stm
            
            Me.FullName = sFullName
            Set stm = Server.CreateObject("ADODB.Stream")
            stm.Type = 2
            stm.Mode = 3
            stm.Open
            stm.LoadFromFile sFullName
            stm.Type = 1
            bnsContent = stm.Read
            stm.Close
            Set stm = Nothing
        End Function
        
        Public Function Save(ByRef sFullName, ByVal iWriteMode)
            Dim stm, bns
            Const sSOURCE = "Save(sFullName, iWriteMode)"
            
            'On Error Resume Next
            If Trim(sFullName) = "" Or Right(sFullName, 1) = "\" Then Exit Function
            Set stm = Server.CreateObject("ADODB.Stream")
            stm.Type = 1
            stm.Open
            stm.Write bnsContent
            stm.SaveToFile sFullName, iWriteMode
            stm.Close
            Set stm = Nothing
            If err.number <> 0 Then 
                Save = "时间戳:" & Now() & " [" & csClass & "." & sSOURCE & "] 发生错误(sFullName = '" & sFullName & ", iWriteMode = '" & iWriteMode & ")。错误号:" & Err.number & ";错误描述:" & Err.Description & ";错误源:" & Err.Source & ";"
            Else
                Save = "OK"
            End If
            On Error Goto 0
        End Function
    End Class
    %>
    

    五、CFormDataGetter.asp 文件,上传文件最为核心的程序

    <!--#include file="CFile.asp"-->
    <% 
    '**************************************************** 
    '文件名: CFormDataGetter.asp
    '描  述:这是一个页面表单容器,可以分析每个表单元素的内容,也可用作无组件上传类。
    '	
    '
    '**************************************************** 
    '# *Using CFile.asp*
    
    Class CFormDataGetter
        ' 表单字节大小
        Private lFormSize
        ' 表单数据
        Private bnsFormData
        ' 表单数据中字段间的分隔符
        private bnsDivider
        Private bnsVbCrLf
        Private lChunkBytes
        Private lReadedBytes
        
        ' 字段分隔符
        Public Property Get FieldDivider()
            FieldDivider = bnsDivider
        End Property
        
        Public Property Get FormSize() 
            FormSize = lFormSize
        End Property
        
        Public Property Get FormBinaryData()
            FormBinaryData = bnsFormData
        End Property
        
        Public Property Get Chunk()
            Chunk = lChunkBytes
        End Property
        
        Public Property Let Chunk(ByVal l)
            lChunkBytes = l
        End Property
        
        Public Property Get ReadedBytes()
            ReadedBytes = lReadedBytes
        End Property
        
        Public Property Let ReadedBytes(ByVal l)
            lReadedBytes = l
        End Property
        
        Public Property Get LogPath()
            On Error Resume Next
            LogPath = Session("ssnLogPath")
            If Err.number <> 0 Then
                LogPath = ""
            End If
            On Error Goto 0
        End Property
        
        Public Property Let LogPath(ByVal s)
            Session("ssnLogPath") = s
        End Property 
        
        Public Property Get LogFileName()
            On Error Resume Next
            LogFileName = Session("ssnLogFileName")
            If Err.number <> 0 Then
                LogFileName = "DataReadLog.xml"
            End If
            On Error Goto 0
        End Property
        
        Public Property Let LogFileName(ByRef s)
            Session("ssnLogFileName") = s
        End Property
            
        Private Sub Class_Initialize
            ' 分块数
            Dim lChunks, i, lBytesToRead, oStream
            bnsVbCrLf = ChrB(13) & ChrB(10)
            
            ' 获取表单的总字节数
            lFormSize = Request.TotalBytes
            
            Me.Chunk = 100 * 1024
            Me.ReadedBytes = 0
            
            If lFormSize > 0 And Me.Chunk > 0 Then
                If lFormSize Mod Me.Chunk = 0 Then
                    lChunks = lFormSize \ Me.Chunk
                Else
                    lChunks = lFormSize \ Me.Chunk + 1
                End If
                
                Set oStream = Server.CreateObject("ADODB.Stream")
                oStream.Type = 1
                oStream.Mode = 3
                oStream.Open 
                
                ' 分块读取数据
                For i = 1 To lChunks
                    ' 如果剩余的数据多于分块,则读进一个分块,否则读进剩余数据
                    If lFormSize - Me.ReadedBytes > Me.Chunk Then
                        lBytesToRead = Me.Chunk
                    Else
                        lBytesToRead = lFormSize - Me.ReadedBytes
                    End If
                    
                    oStream.Write Request.BinaryRead(lBytesToRead)                
                    Me.ReadedBytes = Me.ReadedBytes + lBytesToRead
                    
                    ' 记录读进了多少数据
                    On Error Resume Next
                    'LogDataReaded i, Now(), Me.ReadedBytes, lFormSize
                    'LogDataReadInSession Me.ReadedBytes / lFormSize
                    On Error Goto 0
                Next
                oStream.Position = 0
                bnsFormData = oStream.Read
                
                Set oStream = Nothing
                
                ' 下面开始查找表单数据中字段间的分隔符
                Dim lIndex
                
                lIndex = CLng(InstrB(bnsFormData,bnsVbCrLf))
                If lIndex >= 1 Then
                    ' 成功获取到字段间的分隔符
                    bnsDivider = LeftB(bnsFormData, lIndex - 1)
                Else
                    '
                    bnsDivider = ""
                End If
            Else
                bnsFormData = ""
                bnsDivider = ""
            End If
        End Sub
        
        '
        ' 记录上传了多少?
        '
        Public Function LogDataReaded(ByVal lSerialNumber, ByVal sTimeStamp, ByVal lBytesReaded, ByVal lTotalBytes)
            Dim sFileFullVirtualName, sFileContent, oFS, oFile
            
            sFileFullVirtualName = Me.LogPath & Me.LogFileName
            sFileContent = "<?xml version=""1.0"" encoding=""utf-8""?>"
            sFileContent = sFileContent & "<datareaded>"
            sFileContent = sFileContent & "<serialnumber>" & lSerialNumber & "</serialnumber>"
            sFileContent = sFileContent & "<timestamp>" & sTimeStamp & "</timestamp>"
            sFileContent = sFileContent & "<bytesreaded>" & lBytesReaded & "</bytesreaded>"
            sFileContent = sFileContent & "<totalbytes>" & lTotalBytes & "</totalbytes>"
            sFileContent = sFileContent & "</datareaded>"
            
            Set oFS = Server.CreateObject("Scripting.FileSystemObject")
            Set oFile = oFS.CreateTextFile(Server.MapPath(sFileFullVirtualName), True)
            
            oFile.Write sFileContent
            oFile.Close
            Set oFile = Nothing
            Set oFS = Nothing
            
        End Function
        
        '
        ' 获取指字字段名的二进制串
        '
        Public Function GetFieldBinaryData(ByRef sFieldName)
            Dim bnsBorder, lIndex, lFieldStart, lFieldEnd, lFieldSize
            
            If Me.FormSize <= 0 Then
                GetFieldBinaryData = ""
                Exit Function
            End If
            
            ' 字段开始边界
            bnsBorder = bnsDivider & bnsVBCrLf & ConvertStringToBinary("Content-Disposition: form-data; name=""" & sFieldName & """") & bnsVbCrLf & bnsVbCrLf
            lIndex = InStrB(1, Me.FormBinaryData, bnsBorder)
            If lIndex > 0 Then
                ' 定位到字段内容的开始位置
                lFieldStart = lIndex + LenB(bnsBorder)
                ' 定位到字段内容的结束位置
                lFieldEnd = InStrB(lFieldStart, Me.FormBinaryData, bnsDivider) - 3
                ' 计算字段内容的字节长度
                lFieldSize = lFieldEnd - lFieldStart + 1
                GetFieldBinaryData = MidB(Me.FormBinaryData, lFieldStart, lFieldSize)
            Else
                GetFieldBinaryData = bnsBorder
            End If
        End Function
        
        '
        ' 获取指定字段名的文本串
        '
        Public Function GetFieldTextData(ByRef sFieldName)
            GetFieldTextData = ConvertBinaryToString(GetFieldBinaryData(sFieldName))
        End Function
        
        '
        ' 将一个文本字符串转换成二进制字符串
        '
        Public Function ConvertStringToBinary(ByRef s)
            Dim bns, i
            
            For i = Len(s) To 1 Step -1
                bns = ChrB(Asc(Mid(s, i, 1))) & bns
            Next
            
            ConvertStringToBinary = bns
        End Function
        
        '
        ' 将一个二进制字符串转换成文本字符串
        ' ------------------------------------
        ' 此方法在localhost上能正确使用,得到理想的效果。但是将网站上传到服务器上时,有时会失灵。
        ' 在别的地方看到另一种程序来将二进制字符转换成文本字符串,和我的差不多,但是对于Ascii码大于等于128的,进行跳过,然后使用AscW()对连接两个字符同时进行转换。如下 
        ' Public Function ConvertBinaryToString(ByVal bns)
        '   Dim i, s, sClow
        '   For i = 1 To LenB(bns)
        '       sClow = MidB(bns, i, 1)
        '       If AscB(sClow) < 128 Then
        '           s = s & Chr(AscB(sClow))
        '       Else
        '           i = i + 1
        '           If i <= LenB(bns) Then s = s & Chr(AscW(MidB(bns, i, 1) & sClow))
        '       End If
        '   Next
        '   ConvertBinaryToString = s
        ' End Function
        '
        Public Function ConvertBinaryToString(ByVal bns)
            Dim s, i
            
            s = ""
            For i = LenB(bns) To 1 Step -1
                s = Chr(AscB(MidB(bns, i, 1))) & s
            Next
            
            ConvertBinaryToString = s
        End Function
        
        '
        ' 获取文件
        '
        Public Function GetFile(ByRef sFieldName) 
            Dim bnsBorder, lIndex, lFieldStart, lFieldEnd, lFieldSize, oFile
            
            If Me.FormSize <= 0 Then
                Set GetFile = Nothing
                'AddInfo "表单大小为0字节"
                Exit Function
            Else
                'AddInfo "表单大小为 " & Me.FormSize & " 字节"
            End If
            
            ' 文件二进制流开始边界
            bnsBorder = bnsDivider & bnsVbCrLf & ConvertStringToBinary("Content-Disposition: form-data; name=""" & sFieldName & """; filename=""")
            
            lIndex = InStrB(1, Me.FormBinaryData, bnsBorder)
            
            If lIndex > 0 Then
                Set oFile = New CFile
                ' 以下获取文件完整路径名
                '   定位到第1个字符
                lFieldStart = lIndex + LenB(bnsBorder)
                '   定位到最后1个字符
                lFieldEnd = InStrB(lFieldStart, Me.FormBinaryData, bnsVbCrLf) - 2
                '   计算路径字段内容大小
                lFieldSize = lFieldEnd - lFieldStart + 1
                If lFieldSize > 0 Then
                    ' 文件名
                    oFile.FullName = Cbns2TextStream(MidB(Me.FormBinaryData, lFieldStart, lFieldSize), "utf-8")
                    
                    ' 以下获取文件的MIME类型
                    Dim lPos
                    lPos = InStrB(lFieldEnd, Me.FormBinaryData, ConvertStringToBinary("Content-Type: "))
                    If lPos > 0 Then
                        lFieldStart = lPos + LenB(ConvertStringToBinary("Content-Type: "))
                        lFieldEnd = InStrB(lFieldStart, Me.FormBinaryData, bnsVbCrLf & bnsVbCrLf) - 1
                        lFieldSize = lFieldEnd - lFieldStart + 1
                        If lFieldSize > 0 Then
                            oFile.MIME = ConvertBinaryToString(MidB(Me.FormBinaryData, lFieldStart, lFieldSize))
                        Else 
                            oFile.MIME = ""
                        End If
                    Else
                        oFile.MIME = ""
                    End If
                    
                    ' 以下获取文件内容
                    lPos = lFieldEnd
                    lFieldStart = InStrB(lPos, Me.FormBinaryData, bnsVbCrLf & bnsVbCrLf) + 4
                    lFieldEnd = InStrB(lFieldStart, Me.FormBinaryData, bnsDivider) - 3
                    lFieldSize = lFieldEnd - lFieldStart + 1
                    If lFieldSize <= 0 Or lFieldStart <= 0 Then
                        oFile.BinaryStream = ""
                    Else
                        Dim stmFormBinaryData, stmFileBinaryData
                        Set stmFormBinaryData = Server.CreateObject("ADODB.Stream")
                        Set stmFileBinaryData = Server.CreateObject("ADODB.Stream")
                        stmFormBinaryData.Type = 1
                        stmFormBinaryData.Open
                        stmFormBinaryData.Write Me.FormBinaryData
                        
                        stmFileBinaryData.Type = 1
                        stmFileBinaryData.Open 
                        ' 在ADODB.Stream对象里,索引从0开始,而不是VB的其他地方,索引从1开始
                        'stmFormBinaryData.Position = lFieldStart - 1
                        stmFormBinaryData.Position = 0
                        'stmFormBinaryData.CopyTo stmFileBinaryData, lFieldSize
                        stmFormBinaryData.CopyTo stmFileBinaryData
                        ' 使用MidB()或者LeftB()返回的字符串会自动添加一些别的信息,导致结果二进制串与原来的不太一样
                        'oFile.BinaryStream = MidB(Me.FormBinaryData, lFieldStart, lFieldSize)
                        stmFileBinaryData.Position = lFieldStart - 1
                        oFile.BinaryStream = stmFileBinaryData.Read(lFieldSize)
                        stmFormBinaryData.Close
                        stmFileBinaryData.Close
                        Set stmFormBinaryData = Nothing
                        Set stmFileBinaryData = Nothing
                    End If
                    Set GetFile = oFile
                Else
                    oFile.BinaryStream = ""
                    Set GetFile = oFile
                End If
            Else
                ' 未找到文件二进制流开始边界
                'AddInfo "未找到文件二进制流开始边界"
                'AddInfo "表单数据:" & Cbns2TextStream(Me.FormBinaryData, "utf-8")
                Set GetFile = Nothing
                Exit Function
            End If
        End Function
        
        '
        ' 保存文件
        '
        Public Function SaveFile(ByRef sFieldName, ByRef sFullName, ByVal iWriteMode) 
            Dim bnsBorder, lIndex, lFieldStart, lFieldEnd, lFieldSize, oFile
            
            If Me.FormSize <= 0 Then
                Set GetFile = Nothing
                Exit Function
            End If
            
            ' 文件二进制流开始边界
            bnsBorder = bnsDivider & bnsVbCrLf & ConvertStringToBinary("Content-Disposition: form-data; name=""" & sFieldName & """; filename=""")
            
            lIndex = InStrB(1, Me.FormBinaryData, bnsBorder)
            
            If lIndex > 0 Then
                Set oFile = New CFile
                ' 以下获取文件完整路径名
                '   定位到第1个字符
                lFieldStart = lIndex + LenB(bnsBorder)
                '   定位到最后1个字符
                lFieldEnd = InStrB(lFieldStart, Me.FormBinaryData, bnsVbCrLf) - 2
                '   计算路径字段内容大小
                lFieldSize = lFieldEnd - lFieldStart + 1
                ' 文件名
                oFile.FullName = ConvertBinaryToString(MidB(Me.FormBinaryData, lFieldStart, lFieldSize))
                
                ' 以下获取文件的MIME类型
                Dim lPos
                lPos = lFieldEnd
                lFieldStart = lPos + 18
                lFieldEnd = InStrB(lFieldStart, Me.FormBinaryData, bnsVbCrLf & bnsVbCrLf) - 1
                lFieldSize = lFieldEnd - lFieldStart + 1
                oFile.MIME = ConvertBinaryToString(MidB(Me.FormBinaryData, lFieldStart, lFieldSize))
                
                ' 以下获取文件内容
                lPos = lFieldEnd
                lFieldStart = lPos + 5
                lFieldEnd = InStrB(lFieldStart, Me.FormBinaryData, bnsDivider) - 3
                lFieldSize = lFieldEnd - lFieldStart + 1
                oFile.BinaryStream = MidB(Me.FormBinaryData, lFieldStart, lFieldSize)
                
                ' 开始保存文件
                Dim stm, stmFile
                
                If Trim(sFullName) = "" Or Right(sFullName, 1) = "\" Then Exit Function
                Set stm = Server.CreateObject("ADODB.Stream")
                Set stmFile = Server.CreateObject("ADODB.Stream")
                stm.Type = 1
                stm.Mode = 3
                stm.Open
                'stm.Write MidB(Me.FormBinaryData, lFieldStart, lFieldSize)
                stm.Write Me.FormBinaryData
                stmFile.Type = 1
                stmFile.Open 
                stm.Position = lFieldStart - 1
                stm.CopyTo stmFile, lFieldSize
                stmFile.SaveToFile sFullName, iWriteMode
                stm.Close
                stmFile.Close
                Set stm = Nothing
                Set stmFile = Nothing
                
                Set SaveFile = oFile
            Else
                Set SaveFile = Nothing
                Exit Function
            End If
        End Function
        
        '
        ' 将指定的二进制串转换成特定编码的文本
        '
        Public Function Cbns2TextStream(ByRef bns, ByRef sCharset)
            Dim stm
            
            Set stm = Server.CreateObject("ADODB.Stream")
            stm.Type = 2
            stm.Open
            stm.WriteText bns
            stm.Position = 0
            If Len(sCharset) > 0 Then stm.Charset = sCharset
            Cbns2TextStream = stm.ReadText
            stm.Close
            Set stm = Nothing
        End Function 
    End Class
    %>
    

    如果你看到这里,但愿你没有它们吓倒。你可以复制它们,或者直接下载源代码,源代码正是我将以上这些代码拷贝下来保存为文件,将压缩成一个压缩文件的,它们经过了测试,可以正常运行。你下载源代码解压缩后可能会发现其中还包含了一个图片文件,而我在上面却没有提到它,因为它并不是必要的组成部分,只是一个提示上传正在进行的视觉符号而已,你可以替换成其他图片或者文字。

    Add comment

    Loading