We have been working on a small project using Infopath 2003 and MOSS to create a faster way to input information in a list. Among the challenges (which was quite a few despite it was software from MS on both "sides") faced was how to enable uploading a file while submitting information to a list.
Infopath 2003 provides a File Attachment Control which enables the end-user to select and attach a file to the form. Infopath automatically encodes the file in Base64 and adds a dynamic header in the front of the file. So we wanted to use the "AddAttachment" web service available to post the file, one of the parameters is a Base64 encoded string. Great! Well, the header added by Infopath is also included in the encoding. We only have Jscript or VBScript to use in Infopath 2003 if we don´t want to start to deploy extra code on the clients (which I try to prefer to stay away from) and the support for decoding/encoding files in those languages are not to great.
So our solution is to extract the filename from the header (code below) and the attach a list item event receiver for "ItemAttachmentAdded" which decode the file, removes the header and saves the file again serverside.
Here is the code for extracting the filename from an Infopath Base64 encoded attachment:
Set node = XDocument.DOM.documentElement.selectSingleNode("/my:myFields/my:FileAttchmentControl")
If(node.text <> "") Then
'typecast the node to base64 as Infopath doesn't do this in node definition
node.DataType = "bin.base64"
'convert base64 node value to binary and store in nodeValue byte array
nodeValue = node.nodeTypedValue
convertByteArrayToHexString = ""
For intCounter = 1 to LenB(nodeValue)
convertByteArrayToHexString = convertByteArrayToHexString & Right("0" & Hex(AscB(MidB(nodeValue, intCounter, 1))), 2)
If(intCounter = 100) Then 'Assuming that the header is no longer that 100 bytes
filename = ""
filenameBuffer = 0
'The length of the filenamebuffer is stored on pos 20-24 (byte), which means 41.47 in Hex and 1 as startpos for Arrays
filenameBuffer = getFilenameBuffer(convertByteArrayToHexString,41,47)
'Read the filename from position (49 to filenamebuffer * unicode - "\n") as end char
filename = getFileName(convertByteArrayToHexString,49,filenameBuffer*4 + 49 - 2)
for k = startLoop to stopLoop step 2
y1 = Mid(data,k,2)
y2 = CLng("&h" & y1)
y3 = y3 + Int(y2)
filenameBuffer = y3
getFilenameBuffer = filenameBuffer
Function getFileName(data,startLoop, stopLoop)
for k = startLoop to stopLoop step 4
h1 = Mid(data,k,2)
h2 = CLng("&h" & h1)
h3 = Chr(h2)
if(h3 <> "") then
filename = filename & Cstr(h3)
getFileName = filename