Instantly share code, notes, and snippets.

Embed
What would you like to do?
Consuming an InfoPath document and a specified node path, decode all file attachments from the document and return them in a list of memory streams.
public List<System.IO.MemoryStream> getInfoPathAttachments(System.Xml.XmlDocument InfoPathDocument, string nodePath)
{
/// <summary>
/// Grab multiple attachments from an InfoPath form and
/// return them in a list of memory streams.
/// </summary>
List<System.IO.MemoryStream> files = new List<MemoryStream>();
System.Xml.XmlNamespaceManager nm = new System.Xml.XmlNamespaceManager(InfoPathDocument.NameTable);
nm.AddNamespace("my", "http://schemas.microsoft.com/office/infopath/2003/myXSD/2014-07-12T15:29:09");
//This needs to be the XML path to the node that contains the attachments.
//In our case the attachments were litterally hanging off the base node.
System.Xml.XmlNodeList xnl = InfoPathDocument.SelectNodes(nodePath, nm);
//It is crucially important to note that we're using the SelectNodes() PLURAL method here!
foreach (System.Xml.XmlNode nod in xnl)
{
string attachmentInBase64Text = nod.InnerText;
byte[] attachmentByteArray = Convert.FromBase64String(attachmentInBase64Text);
int fileNameBufferLength = attachmentByteArray[20] * 2;
//Get the filename with extension.
byte[] fileNameBuffer = new byte[fileNameBufferLength];
for (int i = 0; i < fileNameBufferLength; i++)
{
fileNameBuffer[i] = attachmentByteArray[24 + i];
}
string fileName = new string(UnicodeEncoding.Unicode.GetChars(fileNameBuffer));
fileName = fileName.Substring(0, fileName.Length - 1);
//A byte array for the file content.
byte[] fileContent = new byte[attachmentByteArray.Length - (24 + fileNameBufferLength)];
for (int i = 0; i < fileContent.Length; i++)
{
fileContent[i] = attachmentByteArray[24 + fileNameBufferLength + i];
}
System.IO.MemoryStream ms = new MemoryStream(fileContent);
files.Add(ms);
}
return files;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment