The below code is for converting a zip file to base64 format.
Dim inByteArray, base64Encoded,
Const TypeBinary = 1
inByteArray = readBytes("F:path/file.zip")
base64Encoded = encodeBase64(inByteArray)
Private Function readBytes(file)
Dim inStream
' ADODB stream object used
Set inStream = 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
I tried first with a zip file of size 3MB It worked fine . But when I try with a zip file of size 34 MB it says
Not enough storage is available to complete this operation!
at line
encodeBase64 = EL.Text
Is there any way that I can handle zip files of all sizes because my file sizes are mostly 30MB or more.
edited 2017/01/10 - (original answer keeped at bottom)
edited 2017/01/10 - (again) - some (not all) of my problems with timeouts were caused by a disk failure.
Problems with input data were handled by splitting the conversion operations. Now code has been changed to handle buffering in two different ways: for small files (by default configured for files up to
10MB
) a memory stream is used to store the output, but for big files (greater than10MB
) a temporary file is used (see notes after code).Will the memory be a problem?
Yes. Available memory is still a limit. Anyway I have tested the code with
cscript.exe
running as a 32bit process with 90MB files and in 64bit mode with 500MB files without problems.Why two methods?
The
stream
method is faster (all operations are done in memory without string concatenations), but it requires more memory as it will have two copies of the same data at the end of the function: there will be one copy inside the stream and one in the string that will be returnedThe temporary file method is slower as the buffered data will be written to disk, but as there is only one copy of the data, it requires less memory.
The
10MB
limit used to determine if we will use or not a temporary file is just a pesimistic configuration to prevent problems in 32bit mode. I have processed 90MB files in 32bit mode without problems, but just to be safe.Why the
stream
is configured asUnicode
and the data is retrieved via.Read()
method?Because the
stream.ReadText()
is slow. Internally it makes a lot of string conversions/checks (yes, it is advised in the documentation) that make it unusable in this case.Below it is the original answer. It is simpler and avoids the memory problem in the conversion but, for large files, it is not enough.
Split the read/encode process
Notes:
No, it is not bulletproof. You are still limited by the space needed to construct the output string. For big files, you will need to use an output file, writing partial results until all the input has been processed.
3145716 is just the nearest multiple of 54 (the number of input bytes for each base64 output line) lower than 3145728 (3MB).