Insert file attachment control in infopath form and submit that form in form library
Design This form using infopath from
1.Open infopath form
2.In top menu bar u can see controls in tat choose under objects->choose File attachment control
3 .Add 3 buttons named attach,submit and close.
For attachment field we have to write coding otherwise we cannot add attachment field as fields value.
We have to encode and decode and write code for attach & submit button to save attached documents in document library
In infopath form under developer->code editor->visual studio will open->in this create class file.cs as attachment encoding and paste the below coding
Encoder .cs coding
using System;
using System.IO;
using System.Collections.Generic;
using System.Text;
using System.Security.Cryptography;
namespace name
{
class InfoPathAttachmentEncoder
{
private string base64EncodedFile = string.Empty;
private string fullyQualifiedFileName;
/// <summary>
/// Creates an encoder to create an InfoPath attachment string.
/// </summary>
/// <param name="fullyQualifiedFileName"></param>
public InfoPathAttachmentEncoder(string fullyQualifiedFileName)
{
if (fullyQualifiedFileName == string.Empty)
throw new ArgumentException("Must specify file name", "fullyQualifiedFileName");
if (!File.Exists(fullyQualifiedFileName))
throw new FileNotFoundException("File does not exist: " + fullyQualifiedFileName, fullyQualifiedFileName);
this.fullyQualifiedFileName = fullyQualifiedFileName;
}
/// <summary>
/// Returns a Base64 encoded string.
/// </summary>
/// <returns>String</returns>
public string ToBase64String()
{
if (base64EncodedFile != string.Empty)
return base64EncodedFile;
// This memory stream will hold the InfoPath file attachment buffer before Base64 encoding.
MemoryStream ms = new MemoryStream();
// Obtain the file information.
using (BinaryReader br = new BinaryReader(File.Open(fullyQualifiedFileName, FileMode.Open, FileAccess.Read, FileShare.Read)))
{
string fileName = Path.GetFileName(fullyQualifiedFileName);
uint fileNameLength = (uint)fileName.Length + 1;
byte[] fileNameBytes = Encoding.Unicode.GetBytes(fileName);
using (BinaryWriter bw = new BinaryWriter(ms))
{
// Write the InfoPath attachment signature.
bw.Write(new byte[] { 0xC7, 0x49, 0x46, 0x41 });
// Write the default header information.
bw.Write((uint)0x14); // size
bw.Write((uint)0x01); // version
bw.Write((uint)0x00); // reserved
// Write the file size.
bw.Write((uint)br.BaseStream.Length);
// Write the size of the file name.
bw.Write((uint)fileNameLength);
// Write the file name (Unicode encoded).
bw.Write(fileNameBytes);
// Write the file name terminator. This is two nulls in Unicode.
bw.Write(new byte[] { 0, 0 });
// Iterate through the file reading data and writing it to the outbuffer.
byte[] data = new byte[64 * 1024];
int bytesRead = 1;
while (bytesRead > 0)
{
bytesRead = br.Read(data, 0, data.Length);
bw.Write(data, 0, bytesRead);
}
}
}
// This memorystream will hold the Base64 encoded InfoPath attachment.
MemoryStream msOut = new MemoryStream();
using (BinaryReader br = new BinaryReader(new MemoryStream(ms.ToArray())))
{
// Create a Base64 transform to do the encoding.
ToBase64Transform tf = new ToBase64Transform();
byte[] data = new byte[tf.InputBlockSize];
byte[] outData = new byte[tf.OutputBlockSize];
int bytesRead = 1;
while (bytesRead > 0)
{
bytesRead = br.Read(data, 0, data.Length);
if (bytesRead == data.Length)
tf.TransformBlock(data, 0, bytesRead, outData, 0);
else
outData = tf.TransformFinalBlock(data, 0, bytesRead);
msOut.Write(outData, 0, outData.Length);
}
}
msOut.Close();
return base64EncodedFile = Encoding.ASCII.GetString(msOut.ToArray());
}
}
}
using System.IO;
using System.Collections.Generic;
using System.Text;
using System.Security.Cryptography;
namespace name
{
class InfoPathAttachmentEncoder
{
private string base64EncodedFile = string.Empty;
private string fullyQualifiedFileName;
/// <summary>
/// Creates an encoder to create an InfoPath attachment string.
/// </summary>
/// <param name="fullyQualifiedFileName"></param>
public InfoPathAttachmentEncoder(string fullyQualifiedFileName)
{
if (fullyQualifiedFileName == string.Empty)
throw new ArgumentException("Must specify file name", "fullyQualifiedFileName");
if (!File.Exists(fullyQualifiedFileName))
throw new FileNotFoundException("File does not exist: " + fullyQualifiedFileName, fullyQualifiedFileName);
this.fullyQualifiedFileName = fullyQualifiedFileName;
}
/// <summary>
/// Returns a Base64 encoded string.
/// </summary>
/// <returns>String</returns>
public string ToBase64String()
{
if (base64EncodedFile != string.Empty)
return base64EncodedFile;
// This memory stream will hold the InfoPath file attachment buffer before Base64 encoding.
MemoryStream ms = new MemoryStream();
// Obtain the file information.
using (BinaryReader br = new BinaryReader(File.Open(fullyQualifiedFileName, FileMode.Open, FileAccess.Read, FileShare.Read)))
{
string fileName = Path.GetFileName(fullyQualifiedFileName);
uint fileNameLength = (uint)fileName.Length + 1;
byte[] fileNameBytes = Encoding.Unicode.GetBytes(fileName);
using (BinaryWriter bw = new BinaryWriter(ms))
{
// Write the InfoPath attachment signature.
bw.Write(new byte[] { 0xC7, 0x49, 0x46, 0x41 });
// Write the default header information.
bw.Write((uint)0x14); // size
bw.Write((uint)0x01); // version
bw.Write((uint)0x00); // reserved
// Write the file size.
bw.Write((uint)br.BaseStream.Length);
// Write the size of the file name.
bw.Write((uint)fileNameLength);
// Write the file name (Unicode encoded).
bw.Write(fileNameBytes);
// Write the file name terminator. This is two nulls in Unicode.
bw.Write(new byte[] { 0, 0 });
// Iterate through the file reading data and writing it to the outbuffer.
byte[] data = new byte[64 * 1024];
int bytesRead = 1;
while (bytesRead > 0)
{
bytesRead = br.Read(data, 0, data.Length);
bw.Write(data, 0, bytesRead);
}
}
}
// This memorystream will hold the Base64 encoded InfoPath attachment.
MemoryStream msOut = new MemoryStream();
using (BinaryReader br = new BinaryReader(new MemoryStream(ms.ToArray())))
{
// Create a Base64 transform to do the encoding.
ToBase64Transform tf = new ToBase64Transform();
byte[] data = new byte[tf.InputBlockSize];
byte[] outData = new byte[tf.OutputBlockSize];
int bytesRead = 1;
while (bytesRead > 0)
{
bytesRead = br.Read(data, 0, data.Length);
if (bytesRead == data.Length)
tf.TransformBlock(data, 0, bytesRead, outData, 0);
else
outData = tf.TransformFinalBlock(data, 0, bytesRead);
msOut.Write(outData, 0, outData.Length);
}
}
msOut.Close();
return base64EncodedFile = Encoding.ASCII.GetString(msOut.ToArray());
}
}
}
Decoder .cs coding
using System;
using System.IO;
using System.Collections.Generic;
using System.Text;
namespace name
{
class InfoPathAttachmentDecoder
{
private const int SP1Header_Size = 20;
private const int FIXED_HEADER = 16;
private int fileSize;
private int attachmentNameLength;
private string attachmentName;
private byte[] decodedAttachment;
/// <summary>
/// Accepts the Base64 encoded string
/// that is the attachment.
/// </summary>
public InfoPathAttachmentDecoder(string theBase64EncodedString)
{
byte[] theData = Convert.FromBase64String(theBase64EncodedString);
using (MemoryStream ms = new MemoryStream(theData))
{
BinaryReader theReader = new BinaryReader(ms);
DecodeAttachment(theReader);
}
}
private void DecodeAttachment(BinaryReader theReader)
{
//Position the reader to obtain the file size.
byte[] headerData = new byte[FIXED_HEADER];
headerData = theReader.ReadBytes(headerData.Length);
fileSize = (int)theReader.ReadUInt32();
attachmentNameLength = (int)theReader.ReadUInt32() * 2;
byte[] fileNameBytes = theReader.ReadBytes(attachmentNameLength);
//InfoPath uses UTF8 encoding.
Encoding enc = Encoding.Unicode;
attachmentName = enc.GetString(fileNameBytes, 0, attachmentNameLength - 2);
decodedAttachment = theReader.ReadBytes(fileSize);
}
public void SaveAttachment(string saveLocation)
{
string fullFileName = saveLocation;
if (!fullFileName.EndsWith(Path.DirectorySeparatorChar.ToString()))
{
fullFileName += Path.DirectorySeparatorChar;
}
fullFileName += attachmentName;
if (File.Exists(fullFileName))
File.Delete(fullFileName);
FileStream fs = new FileStream(fullFileName, FileMode.CreateNew);
BinaryWriter bw = new BinaryWriter(fs);
bw.Write(decodedAttachment);
bw.Close();
fs.Close();
}
public string Filename
{
get { return attachmentName; }
}
public byte[] DecodedAttachment
{
get { return decodedAttachment; }
}
}
}
using System.IO;
using System.Collections.Generic;
using System.Text;
namespace name
{
class InfoPathAttachmentDecoder
{
private const int SP1Header_Size = 20;
private const int FIXED_HEADER = 16;
private int fileSize;
private int attachmentNameLength;
private string attachmentName;
private byte[] decodedAttachment;
/// <summary>
/// Accepts the Base64 encoded string
/// that is the attachment.
/// </summary>
public InfoPathAttachmentDecoder(string theBase64EncodedString)
{
byte[] theData = Convert.FromBase64String(theBase64EncodedString);
using (MemoryStream ms = new MemoryStream(theData))
{
BinaryReader theReader = new BinaryReader(ms);
DecodeAttachment(theReader);
}
}
private void DecodeAttachment(BinaryReader theReader)
{
//Position the reader to obtain the file size.
byte[] headerData = new byte[FIXED_HEADER];
headerData = theReader.ReadBytes(headerData.Length);
fileSize = (int)theReader.ReadUInt32();
attachmentNameLength = (int)theReader.ReadUInt32() * 2;
byte[] fileNameBytes = theReader.ReadBytes(attachmentNameLength);
//InfoPath uses UTF8 encoding.
Encoding enc = Encoding.Unicode;
attachmentName = enc.GetString(fileNameBytes, 0, attachmentNameLength - 2);
decodedAttachment = theReader.ReadBytes(fileSize);
}
public void SaveAttachment(string saveLocation)
{
string fullFileName = saveLocation;
if (!fullFileName.EndsWith(Path.DirectorySeparatorChar.ToString()))
{
fullFileName += Path.DirectorySeparatorChar;
}
fullFileName += attachmentName;
if (File.Exists(fullFileName))
File.Delete(fullFileName);
FileStream fs = new FileStream(fullFileName, FileMode.CreateNew);
BinaryWriter bw = new BinaryWriter(fs);
bw.Write(decodedAttachment);
bw.Close();
fs.Close();
}
public string Filename
{
get { return attachmentName; }
}
public byte[] DecodedAttachment
{
get { return decodedAttachment; }
}
}
}
Attach and submit button code
using Microsoft.Office.InfoPath;
using System;
using System.Xml;
using System.Xml.XPath;
using Microsoft.SharePoint;
namespace name
{
public partial class FormCode
{
// Member variables are not supported in browser-enabled forms.
// Instead, write and read these values from the FormState
// dictionary using code such as the following:
//
// private object _memberVariable
// {
// get
// {
// return FormState["_memberVariable"];
// }
// set
// {
// FormState["_memberVariable"] = value;
// }
// }
// NOTE: The following procedure is required by Microsoft InfoPath.
// It can be modified using Microsoft InfoPath.
public void InternalStartup()
{
((ButtonEvent)EventManager.ControlEvents["btnAttach"]).Clicked += new ClickedEventHandler(btnAttach_Clicked);
((ButtonEvent)EventManager.ControlEvents["btnSave"]).Clicked += new ClickedEventHandler(btnSave_Clicked);
//((ButtonEvent)EventManager.ControlEvents["CTRL5_5"]).Clicked += new ClickedEventHandler(CTRL5_5_Clicked);
((ButtonEvent)EventManager.ControlEvents["CTRL11_5"]).Clicked += new ClickedEventHandler(CTRL11_5_Clicked);
}
//Attach Field code
public void btnAttach_Clicked(object sender, ClickedEventArgs e)
public void btnAttach_Clicked(object sender, ClickedEventArgs e)
{
//Create an XmlNamespaceManager
XmlNamespaceManager ns = this.NamespaceManager;
//Create an XPathNavigator object for the Main data source
XPathNavigator xnMain = this.MainDataSource.CreateNavigator();
//Create an XPathNavigator object for the attachment node
XPathNavigator xnAttNode = xnMain.SelectSingleNode("/my:myFields/my:theAttachmentField", ns);
//Create an XPathNavigator object for the filename node
XPathNavigator xnFileName = xnMain.SelectSingleNode("/my:myFields/my:theAttachmentName", ns);
//Obtain the text of the filename node.
string fileName = xnFileName.Value;
if (fileName.Length > 0)
{
//Encode the file and assign it to the attachment node.
InfoPathAttachmentEncoder myEncoder = new InfoPathAttachmentEncoder(fileName);
//Check for the "xsi:nil" attribute on the file attachment node and remove it
//before setting the value to attach the filerRemove the "nil" attribute
if (xnAttNode.MoveToAttribute("nil", "http://www.w3.org/2001/XMLSchema-instance"))
xnAttNode.DeleteSelf();
//Attach the file
xnAttNode.SetValue(myEncoder.ToBase64String());
}
}
//public void CTRL5_5_Clicked(object sender, ClickedEventArgs e)
//save button code
public void btnSave_Clicked(object sender, ClickedEventArgs e)
{
// Retrieve the value of the attachment in the InfoPath form
XPathNavigator ipFormNav = MainDataSource.CreateNavigator();
XPathNavigator nodeNav = ipFormNav.SelectSingleNode(
"/my:myFields/my:theAttachmentField", NamespaceManager);
string attachmentValue = string.Empty;
if (nodeNav != null && !String.IsNullOrEmpty(nodeNav.Value))
{
attachmentValue = nodeNav.Value;
// Decode the InfoPath file attachment
InfoPathAttachmentDecoder dec =
new InfoPathAttachmentDecoder(attachmentValue);
string fileName = dec.Filename;
byte[] data = dec.DecodedAttachment;
// Add the file to a document library
// using (SPSite site = new SPSite("site collection name"))
using(SPSite site = SPContext.Current.Site)
{
using (SPWeb web = site.OpenWeb())
{
web.AllowUnsafeUpdates = true;
SPFolder docLib = web.Folders["library name];
docLib.Files.Add(fileName, data);
web.AllowUnsafeUpdates = false;
web.Close();
}
site.Close();
}
}
}
Then save and publish.
Thanks for sharing the complete source code to insert a file attachment control. I have been trying to implement the same but is not fully aware of all these controls and functions. I will make use of the above code.
ReplyDeleteinfopath signing