Udostępnij za pośrednictwem


Transferring attachment file from Web Service to InfoPath

I previously posted about InfoPath and Web Service data connections. Back then I didn't mention that you could use the same method to transfer InfoPath attachments as well. It's actually pretty straightforward thing. All you need to do at the web service is wrap up you existing file data to InfoPath file attachment format and return it as BASE64 encoded. It sounds easy and it really is. Well enough talking... let's checkout the code!

First we need method that creates InfoPath attachment from byte array. It could be something like this:

  1  static public String CreateInfoPathAttachment(String fileName, byte[] fileData)
 2  {
 3      // This memory stream for InfoPath attachment buffer before Base64 encoding.
 4      using (MemoryStream ms = new MemoryStream())
 5      {
 6          uint fileNameLength = (uint)fileName.Length + 1;
 7          byte[] fileNameBytes = Encoding.Unicode.GetBytes(fileName);
 8
 9          using (BinaryWriter bw = new BinaryWriter(ms))
10          {
11              // Write the InfoPath attachment signature. 
12              bw.Write(new byte[] { 0xC7, 0x49, 0x46, 0x41 });
13
14              // Write the default header information.
15              bw.Write((uint)0x14); // size
16              bw.Write((uint)0x01); // version
17              bw.Write((uint)0x00); // reserved
18
19              // Write the file size.
20              bw.Write((uint)fileData.Length);
21  
22              // Write the size of the file name.
23              bw.Write((uint)fileNameLength);
24  
25              // Write the file name (Unicode encoded).
26              bw.Write(fileNameBytes);
27  
28              // Write the file name terminator. This is two nulls in Unicode.
29              bw.Write(new byte[] { 0, 0 });
30              bw.Write(fileData);
31          }
32          return Convert.ToBase64String(ms.ToArray());
33      }
34  }

This code has been "copy-pasted" mainly from this source. However there is unnecessary code (=my opinion) so I have changed it a little bit. I prefer using the existing ToBase64String method (unlike in original code sample).

Now all you need to do at you web service is to pass filename and data to the method and it creates BASE64 encoded string that can be returned to the InfoPath.

 1  ...
2  String fileName;
3  DocumentContainer myDocument;
4  ...
5  byte[] fileData = File.ReadAllBytes(fileName);
6  myDocument.Size = fileData.Length;
7  myDocument.Document = CreateInfoPathAttachment(fileName, fileData);
8  return myDocument;

In my example I use similar approach as in my previous example. I have Document struct that has (in this case) at least to fields: size and document. And in InfoPath I could map those fields exactly as I explained in my earlier post. Now you just map Document field to your InfoPath attachment and that's it:
 
And what makes this really nice... it works also with Forms Services as well! Of course this idea could be also otherway around... so you could sent file from InfoPath to web service using the same underlying idea. In that case you should only parse the InfoPath attachment so that you get the original filename and filedata. Read more about this case in here.

Anyways... Happy hacking!

J

Comments

  • Anonymous
    March 02, 2007
    very cool thank you for sharing

  • Anonymous
    March 03, 2007
    Hi mmeija! No problem... It's my pleasure to tell stuff that I know. I'm just glad that you like it :) Many times I just type in something weird that probably isn't that useful to anyone. But it still helps me since I can stop thinking about the subject that I have written about :) J

  • Anonymous
    February 24, 2008
    Very cool article, thx for sharing. I do have one question tho, the BASE64 string that returns, appears to be the original infopath xml file instead of the attachment that is included within the infopath file .... Do you have any idea how this is possible? I'm using Infopath 2007 forms btw Greetings F

  • Anonymous
    May 19, 2008
    How would you use this code to rename an existing attachment?

  • Anonymous
    January 15, 2009
    I have an base64 node in infopath... I'm writting jscript code... how can I put a null value or an empty value this is my error. (spanish) when I want to submit Error: Sólo se admiten datos binarios con codificación base64

  • Anonymous
    October 28, 2009
    hi! Nice article. I am not sure about the return type.. When I import web service method to the infopath it says that attachment it string type and not the bas64binary, which is the data type of the attachment in infopath. Any thoughts Miha

  • Anonymous
    October 28, 2009
    I've changed the return type to byte[] in web service. so The data comes to infopath form, but I can not bind it to the file attachment control. How can I do that? Thanks in advance!!

  • Anonymous
    June 14, 2011
    Hi I retrieve data for my form from a webservice which works well. Say for a textbox field I set the main datasource field to the secondary datasource field (Retrieved from webservice). However there is no such option for a file attachment. How can I do this? Thanks