El Blanco's Office 2007 Blog

Tuesday, July 11, 2006

InfoPath 2007 File Attachment Control and Browser-Enabled Forms

The InfoPath 2007 File Attachment control can be used to upload documents into an InfoPath form, and works with both InfoPath client and browser-based forms. Dragging a File Attachment control onto the design surface adds a new field into the data source of type "Picture or File Attachment (base64)".

This
link describes the technical details on how this field is formatted.

Basically, there is a header which is of length 24 bytes + length of the filename. Following this head is the file contents. These are base64 encoded.

To work with the uploaded file in .NET code in the InfoPath form you can use code similar to the following (which shows a button handler that copies the uploaded file to a local directory):

public void Button_Clicked(object sender, ClickedEventArgs e)
{
XPathNavigator docXN = this.CreateNavigator();
XPathNavigator opnXN = docXN.SelectSingleNode

("/my:myFields/my:FileAttachment",
this.NamespaceManager);
byte[] attachmentNodeBytes = Convert.FromBase64String
(opnXN.ToString());

// Position 20 contains a DWORD indicating the length of the
// filename buffer. The filename is stored as Unicode so the
// length is multiplied by 2.
int fnLength = attachmentNodeBytes[20] * 2;
byte[] fnBytes = new byte[fnLength];

// The actual filename starts at position 24 . . .

for (int i = 0; i <>
{
fnBytes[i] = attachmentNodeBytes[24 + i];
}

// Convert the filename bytes to a string. The string

// terminates with \0 so the actual filename is the
// original filename minus the last character !
char[] charFileName = UnicodeEncoding.Unicode.GetChars(fnBytes);
string fileName = new string(charFileName);
fileName = fileName.Substring(0, fileName.Length - 1);

// The file is located after the header, which is 24 bytes long

// plus the length of the filename.
byte[] fileContents = new byte[attachmentNodeBytes.Length - (24 + fnLength)];

for (int i = 0; i < fileContents.Length; ++i)
{
fileContents[i] = attachmentNodeBytes[24 + fnLength + i];
}

// We now have an array of bytes (fileContents) which we can
// do what we like with. I'll write them to a temporary file
FileStream fs = new FileStream(@"C:\Temp\InfoPath Test\" + fileName, FileMode.Create);
fs.Write(fileContents, 0, fileContents.Length); fs.Close();
}

Note that since this code is part of the InfoPath 2007 form the InfoPath form will need to have full trust (Tools -> Form Options -> Security and Trusts tab) and hence will need to be Admin deployed to the Microsoft Office SharePoint Server 2007 via Central Administration (don't forget to publish the form to a network location first !).

I'm going to try to incorporate this technique into an InfoPath form used in a custom developed workflow developed using the Sequential SharePoint Workflow template from the Enterprise Content Management Starter Kit, which can be downloaded here.

12 Comments:

  • Nice work... I'm having trouble with an InfoPath form into a SharePoint list and then rollups...

    By Anonymous Anonymous, at 10:21 pm  

  • InfoJet Service, a product likes InfoPath Forms Services!
    http://www.infojetsoft.com

    By Anonymous Anonymous, at 7:54 am  

  • Almost works - wrong slash in your JavaScript segment. text/javascript and not text\javascript.

    Apart from that, Thanks for the post - it was a life-saver!

    By Blogger Tiggr, at 2:38 am  

  • great, just what i needed. Thank you

    By Blogger Unknown, at 1:34 pm  

  • Great article!! Thanks it has really helped in creating the files in my desired location.

    Just a little note, there is a minor coding error:

    // The actual filename starts at position 24 . . .
    for (int i = 0; i != fnLength; i++)

    By Anonymous Anonymous, at 5:02 am  

  • I CANT get the base64 attachment added when publishing form to my SharePoint server. I guess I need some more detailed explanation. I'd appreaciate your help. Thanks.

    By Anonymous Anonymous, at 3:20 pm  

  • Anonymous - what exact issue are you seeing ? If you give more details I may be able to assist.

    Thanks,
    Chris

    By Blogger Chris White, at 3:42 pm  

  • I have a text box on the form, "FormatName". How can I save files based on above field? If the actual name of the attached file is "abc.txt", how can it be stored as of "xyz.txt" when value of "FormatName" is xyz. Thanks

    By Anonymous Anonymous, at 8:02 pm  

  • Anonymous,

    It's easy to write the file with whatever name you desire - the code in the article details how to get a byte array. Once you have this the article simply writes it to a temporary file, but you can do with it whatever you like !!!

    Hope this helps,

    Chris

    By Blogger Chris White, at 8:11 am  

  • How can I rename the attachment? If attachment is "FileA.doc" how can I rename this attachment it to "FileB.doc" and leave it attached to the form.

    Thank you.

    By Anonymous Anonymous, at 6:32 pm  

  • Hello,

    I've got a question: how to extract attachments from browser-enabled forms to avoid postback from server to client's browser when refresing form after submitting attachment?

    By Anonymous Anonymous, at 10:02 pm  

  • I just started using InfoPath about a month ago. This tool would be great for a project that I am working on. However, I don't have much programming experience. If it's not too much trouble, can somebody help me implement this code? Will somebody give me, a beginner, step by step instructions to implement the code? thank you--Lawson

    By Blogger Lawson, at 4:49 am  

Post a Comment

<< Home