【问题标题】:Base64 Encode .JPG from request in classic ASP/VBScriptBase64 编码 .JPG 从经典 ASP/VBScript 中的请求
【发布时间】:2014-07-14 17:11:53
【问题描述】:

我已经坚持了几天了,没有任何进展。使用经典 ASP,我需要获取一个上传的 .JPG 文件(来自 html 表单输入 type='file')并对其进行 base64 编码,以便我可以将其发送到 Java Web 服务。 Java Web 服务只是将图像(在 SQL 图像字段中)存储在数据库中。我认为转换为 BASE64 是在 xml 中传输参数的最佳方式。到目前为止,这是我所拥有的:

HTML:

<label>Upload Picture</label> 
<input name="file" id="file" type="file" size=40 /> <br />

平均售价:

Dim load
  Set load = new Loader
  load.initialize

Dim fileData
  fileData = load.getFileData("file")

Dim fileName
  fileName = LCase(load.getFileName("file"))

Dim fileSize
  fileSize = load.getFileSize("file")


Dim objXML
Dim objNode
Dim strB64

Set objXML = Server.CreateObject("MSXML2.DomDocument.3.0")
Set objNode = objXML.createElement("base64")

objNode.dataType = "bin.base64" 'stores binary as base64 string
objNode.nodeTypedValue = fileData 'binary value

strB64 = objNode.Text

装载机:
加载器有很多代码(如果需要,我可以在这里复制所有代码)。它本质上从请求中获取所有字节并将它们解析为字典对象。以下是它获取数据的方式:

Class Loader
    Private dict

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

    Public Sub Initialize
        If Request.TotalBytes > 0 Then
            Dim binData
                binData = Request.BinaryRead(Request.TotalBytes)
                getData binData
        End If
    End Sub

    Public Function getFileData(name) '"file"
        If dict.Exists(name) Then
            getFileData = dict(name).Item("Value")
            Else
            getFileData = ""
        End If
    End Function

如果需要,我可以发布解析二进制文件并将其存储在字典中的子程序。



上面的代码给出了这个错误:

msxml3.dll error '80004005'
Error parsing '????' as bin.base64 datatype. 

在这一行:

objNode.nodeTypedValue = fileData 'binary value

更新:

这里是数据被加载到字典的地方:

Private Sub getData(rawData)
    Dim separator 
        separator = MidB(rawData, 1, InstrB(1, rawData, ChrB(13)) - 1)

    Dim lenSeparator
        lenSeparator = LenB(separator)

    Dim currentPos
        currentPos = 1
    Dim inStrByte
        inStrByte = 1
    Dim value, mValue
    Dim tempValue
        tempValue = ""

    While inStrByte > 0
        inStrByte = InStrB(currentPos, rawData, separator)
        mValue = inStrByte - currentPos

        If mValue > 1 Then
            value = MidB(rawData, currentPos, mValue)

            Dim begPos, endPos, midValue, nValue
            Dim intDict
                Set intDict = Server.CreateObject("Scripting.Dictionary")

                begPos = 1 + InStrB(1, value, ChrB(34))
                endPos = InStrB(begPos + 1, value, ChrB(34))
                nValue = endPos

            Dim nameN
                nameN = MidB(value, begPos, endPos - begPos)

            Dim nameValue, isValid
                isValid = True

                If InStrB(1, value, stringToByte("Content-Type")) > 1 Then

                    begPos = 1 + InStrB(endPos + 1, value, ChrB(34))
                    endPos = InStrB(begPos + 1, value, ChrB(34))

                    If endPos = 0 Then
                        endPos = begPos + 1
                        isValid = False
                    End If

                    midValue = MidB(value, begPos, endPos - begPos)
                        intDict.Add "FileName", trim(byteToString(midValue))

                    begPos = 14 + InStrB(endPos + 1, value, stringToByte("Content-Type:"))
                    endPos = InStrB(begPos, value, ChrB(13))

                    midValue = MidB(value, begPos, endPos - begPos)
                        intDict.Add "ContentType", trim(byteToString(midValue))

                    begPos = endPos + 4
                    endPos = LenB(value)

                    nameValue = MidB(value, begPos, ((endPos - begPos) - 1))
                Else
                    nameValue = trim(byteToString(MidB(value, nValue + 5)))
                End If

                If isValid = True Then

                    intDict.Add "Value", nameValue
                    intDict.Add "Name", nameN

                    dict.Add byteToString(nameN), intDict
                End If
        End If

        currentPos = lenSeparator + inStrByte
    Wend
End Sub

Private Function stringToByte(toConv)
    Dim tempChar, i
     For i = 1 to Len(toConv)
        tempChar = Mid(toConv, i, 1)
        stringToByte = stringToByte & chrB(AscB(tempChar))
     Next
End Function

Private Function byteToString(toConv)
     dim i
    For i = 1 to LenB(toConv)
        byteToString = byteToString & chr(AscB(MidB(toConv,i,1))) 
    Next
End Function

【问题讨论】:

  • 你能说明你把二进制数据 in 放到字典对象的什么地方吗?
  • 我找到了我的问题的答案并将其发布在下面。为了后代(以及那些只是好奇的人),我还添加了加载到上面字典的方法。谢谢!
  • 我想你错过了从 MultiByte 到 VT_UI1 | VT_ARRAY 的转换,这就是为什么我想看看你是如何将数据放入字典的。很高兴您能够自己解决。

标签: file-upload vbscript asp-classic binary base64


【解决方案1】:

我终于找到了有用的东西!这是链接: http://www.motobit.com/tips/detpg_binarytostring/

我遇到的问题是 BinaryRead 中的数据是多字节数据(ASP 不能很好地处理它)。多字节数据必须转换为 VT_UI1 | VT_ARRAY 以便通过 Dom 文档对象(或几乎任何其他功能 - 包括加载到流)进行 base64 编码。这可以使用 ADO 记录集对象来实现:

Function MultiByteToBinary(MultiByte)
  ' 2000 Antonin Foller, http://www.motobit.com
  ' MultiByteToBinary converts multibyte string To real binary data (VT_UI1 | VT_ARRAY)
  ' Using recordset
  Dim RS, LMultiByte, Binary
  Const adLongVarBinary = 205
  Set RS = CreateObject("ADODB.Recordset")
  LMultiByte = LenB(MultiByte)
  If LMultiByte>0 Then
    RS.Fields.Append "mBinary", adLongVarBinary, LMultiByte
    RS.Open
    RS.AddNew
       RS("mBinary").AppendChunk MultiByte & ChrB(0)
    RS.Update
    Binary = RS("mBinary").GetChunk(LMultiByte)
  End If
  MultiByteToBinary = Binary
End Function

希望这对其他人也有帮助。

【讨论】:

  • 绝对帮助了我。我无法感谢您提供此代码。为了弄清楚这一点,我已经度过了漫长的一周。
【解决方案2】:

让 ADODB.Stream 完成您的繁重工作,这假设您已经将文件保存到磁盘。这些是我使用的 BASE64 的函数,我不能 100% 确定我最初是从哪里得到它们的。

  private function readBytes(file)
    dim inStream
    ' ADODB stream object used
    set inStream = WScript.CreateObject("ADODB.Stream")
    ' open with no arguments makes the stream an empty container
    inStream.Open
    inStream.type= TypeBinary
    inStream.LoadFromFile(file)
    readBytes = inStream.Read()
  end function

  private function encodeBase64(bytes)
    dim DM, EL
    Set DM = CreateObject("Microsoft.XMLDOM")
    ' Create temporary node with Base64 data type
    Set EL = DM.createElement("tmp")
    EL.DataType = "bin.base64"
    ' Set bytes, get encoded String
    EL.NodeTypedValue = bytes
    encodeBase64 = EL.Text
  end function

  private function decodeBase64(base64)
    dim DM, EL
    Set DM = CreateObject("Microsoft.XMLDOM")
    ' Create temporary node with Base64 data type
    Set EL = DM.createElement("tmp")
    EL.DataType = "bin.base64"
    ' Set encoded String, get bytes
    EL.Text = base64
    decodeBase64 = EL.NodeTypedValue
  end function

  private Sub writeBytes(file, bytes)
    Dim binaryStream
    Set binaryStream = CreateObject("ADODB.Stream")
    binaryStream.Type = adTypeBinary
    'Open the stream and write binary data
    binaryStream.Open
    binaryStream.Write bytes
    'Save binary data to disk
    binaryStream.SaveToFile file, adSaveCreateOverWrite
  End Sub

【讨论】:

  • 我使用了类似的东西,但不用担心将文件保存到磁盘,它可以直接从请求流中完成。
  • 您的 base64 编码/解码与我使用的相同(使用 DOM 进行转换)。我尝试使用 Stream,从字典中传递文件,但遇到了关于类型不匹配的类似错误。昨晚我终于找到了答案,并在这里发布。感谢您的回复!
  • 是的。这是因为您从BinaryRead 获得的数据是一个多字节字符串,需要将其转换为VT_UI1 | VT_ARRAY 格式,然后才能与XMLDOM 对象一起使用。
  • 其实我也做同样的事情,我也不把它存盘,只是想回答大家的问题:)我在客户端转换成BASE64。
  • @silver - 你能告诉我你如何在用例中调用这些函数 - 当上传/保存文件时?谢谢
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多