After re-reading my post, I have to agree. So I whipped the code from my Quix toolbox into a quick Gist that will hopefully save someone else the frustration in the future. 😎
The code is pretty self explanatory.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | |
} |
All you have to do to incorporate this into your own C# program is to include it in your project and then call the getInfoPathAttachments() method while passing it two arguments.
The first is the XML document constituting the InfoPath form's XML which is easily loaded to the standard System.Xml.XmlDocument object.
The second is the node path where the attachments are located in your form. In my case, the control was called "Attachment" and was literally hanging straight off the root of the document so my node path was "/my:myFields/my:Attachment".
The method will return a list of MemoryStream objects which you can then process any way you like such as saving to disk or processing further etc.
Happy coding.
C
No comments:
Post a Comment
Comments are moderated only for the purpose of keeping pesky spammers at bay.