In terms of decoding speed, Huajing 2.0 is already very high. However, it still has the following two problems:
1. Use Data_5xsoft.Write Request.BinaryRead(Request.TotalBytes) to read all the data at once, and use RequestData =Data_5xsoft.Read to get all the data at once. When the uploaded data is too large, the upload will fail due to insufficient memory. This should be Use segmented reading method.
2. When saving data, you need to copy it from Data_5xsoft to a temporary stream first. When saving a large file, twice the storage resources are required. When tested in a stand-alone state, it can be found that the saving time increases sharply with the file size, even exceeding the upload time. and decoding time.
The class I wrote uses the method of reading block by block during the decoding process (note: the size of the block is not proportional to the speed. Single-machine testing shows that 64K blocks are much faster than 1M blocks) to solve problem 1. , and at the same time, we use the method of writing ordinary data into the workflow; and writing the file content directly into the file's own stream to solve problem 2.
The code is as follows, the usage is similar to Huajing:
Server.ScriptTimeOut = 600
Class QuickUpload
Private FForm, FFile, Upload_Stream, ConvertStream
property get Form
setForm = FForm
end property
property get File
setFile = FFile
end property
Private Sub Class_Initialize
dim iStart, iEnd, boundary, FieldName, FileName, ContentType, ItemValue, theFile, LineEnd
set FForm=CreateObject("Scripting.Dictionary")
set FFile=CreateObject("Scripting.Dictionary")
set Upload_Stream=CreateObject("Adodb.Stream")
Upload_Stream.mode=3
Upload_Stream.type=1
Upload_Stream.open
set ConvertStream = Server.CreateObject("adodb.stream")
ConvertStream.Mode =3
ConvertStream.Charset="GB2312"
if Request.TotalBytes<1 then Exit Sub
'dStart = CDbl(Time)
'Find the first boundary
iStart = Search(Upload_Stream, ChrB(13)&ChrB(10), 1)
'Get the boundary string
boundary = subString(1, iStart-1, false)
'If it is not the end boundary, then it will loop
do while StrComp(subString(iStart, 2, false),ChrB(13)&ChrB(10))=0
iStart = iStart+2
'Get the form item information header
do while true
iEnd = Search(Upload_Stream, ChrB(13)&ChrB(10), iStart)
'Decompose information header
line = subString(iStart, iEnd-iStart, true)
'Move position
iStart = iEnd+2
if Line="" then Exit do
pos = instr(line,":")
if pos>0 then
if StrComp(left(Line,pos-1),"Content-Disposition",1)=0 then
'Get the form item name
FieldName = ExtractValue(Line,pos+1,"name")
'Get file name
FileName = ExtractValue(Line,pos+1,"filename")
'Delete file path
FileName = Mid(FileName,InStrRev(FileName, "")+1)
elseif StrComp(left(Line,pos-1),"Content-Type",1)=0 then
'Get file type
ContentType = trim(mid(Line,pos+1))
end if
end if
loop
'Get the form item content
if FileName<>"" then
'New file content
set theFile = new FileInfo
theFile.Init FileName, ContentType
'Move the file stream content to the file stream
MoveData Upload_Stream, theFile.Stream, iStart
'Upload data is directly transferred to the file stream, which can reduce file storage time
iEnd = Search(theFile.Stream, boundary, 1)
'Move subsequent data into the workflow
MoveData theFile.Stream, Upload_Stream, iEnd-2
'
FFile.add FieldName, theFile
'Move position
iStart = iStart+2+LenB(boundary)
else
'Find boundaries
iEnd = Search(Upload_Stream, boundary, iStart)
'Get the form item content
ItemValue = subString(iStart, iEnd-2-iStart, true)
'
if FForm.Exists(FieldName) then
FForm.Item(FieldName) = FForm.Item(FieldName) & "," & ItemValue
else
FForm.Add FieldName, ItemValue
end if
'Move position
iStart = iEnd+LenB(boundary)
end if
loop
'Response.Write "parse time:" & FormatNumber((CDbl(Time)-dStart)*24*60*60,-1,-1) & "<br>"
End Sub
Private Function Search(src, str, theStart)
iStart = theStart
pos=0
do while pos=0
'The length is not long enough, read one piece
if src.Size<(iStart+lenb(str)-1) then ReadChunk src
'Get a piece of data, about 64K, which can reduce memory requirements
src.Position = iStart-1
buf = src.Read
'Detect boundaries
pos=InStrB(buf,str)
'If not found, move backward
if pos=0 then iStart = iStart+LenB(buf)-LenB(str)+1
loop
Search = iStart+pos-1
End function
private sub MoveData(Src, Dest, theStart)
Src.Position = theStart-1
Dest.Position = Dest.Size
Src.CopyTo dest
Src.Position = theStart-1
Src.SetEOS
end sub
private function ExtractValue(line,pos,name)
dim t, p
ExtractValue = ""
t = name + "="""
p = instr(pos,line,t)
if p>0 then
n1 = p+len(t)
n2 = instr(n1,line,"""")
if n2>n1 then ExtractValue = mid(line,n1,n2-n1)
end if
end function
Private Function subString(theStart,theLen, ConvertToUnicode)
if theLen>0 then
'When the length is not enough, read a piece of data
if Upload_Stream.Size<theStart+theLen-1 then ReadChunk Upload_Stream
Upload_Stream.Position=theStart-1
Binary =Upload_Stream.Read(theLen)
if ConvertToUnicode then
ConvertStream.Type = 1
ConvertStream.Open
ConvertStream.Write Binary
ConvertStream.Position = 0
ConvertStream.Type = 2
subString = ConvertStream.ReadText
ConvertStream.Close
else
subString = midB(Binary,1)
end if
else
subString = ""
end if
End function
Private Sub ReadChunk(src)
'Read a block, by reading 64K at a time, you can prevent memory overflow when the amount of data is too large
if Response.IsClientConnected = false then Raise "Network connection interrupted"
BytesRead = 65536
src.Position = src.Size
src.Write Request.BinaryRead(BytesRead)
End Sub
'Exception information
Private Sub Raise(Message)
Err.Raise vbObjectError, "QuickUpload", Message
End Sub
Private Sub Class_Terminate
form.RemoveAll
file.RemoveAll
set form=nothing
set file=nothing
Upload_Stream.close
set Upload_Stream=nothing
ConvertStream.Close
setConvertStream=nothing
End Sub
End Class
Class FileInfo
Private FFileName, FFileType, FFileStart, FFileSize, FStream
property get FileName
FileName = FFileName
end property
property get FileType
FileType = FFileType
end property
property get FileSize
FileSize = FStream.Size
end property
property getStream
setStream = FStream
end property
Public Sub Init(AFileName, AFileType)
FFileName = AFileName
FFileType = AFileType
End Sub
Public function SaveAs(FullPath)
dim dr,ErrorChar,i
'dStart = CDbl(Time)
SaveAs=1
if trim(fullpath)="" or right(fullpath,1)="/" then exit function
On Error Resume Next
FStream.SaveToFile FullPath,2
if Err.Number>0 then Response.Write "Error saving data:" & Err.Description & "<br>"
SaveAs=0
'Response.Write "save time:" & FormatNumber((CDbl(Time)-dStart)*24*60*60,-1,-1) & "<br>"
end function
Private Sub Class_Initialize
set FStream=CreateObject("Adodb.Stream")
FStream.mode=3
FStream.type=1
FStream.open
end sub
Private Sub Class_Terminate
FStream.Close
set FStream=nothing
end sub
End Class