Как кодировать и декодировать вложение файла программным способом с помощью Visual C# в InfoPath 2010 или InfoPath 2007
Аннотация
В Microsoft InfoPath 2010, русская версия Или в Microsoft Office InfoPath 2007 можно использовать элемент управления "Вложение файла", чтобы вложить файл в шаблон формы InfoPath. В определенных обстоятельствах может потребоваться закодировать, а затем декодировать файл, присоединенный к элементу управления "Вложение файла". В этом случае для создания кодировщика и декодера можно использовать Microsoft Visual C#. Затем можно использовать кодировщик и декодировщик для кодирования и декодирования вложения файла. В этой статье описывается, как спроектировать шаблон формы InfoPath, который кодирует файл для вложения в форму и декодирует вложение для сохранения в файловой системе.
Для получения дополнительных сведений о том, как это сделать в InfoPath 2003, щелкните следующий номер статьи, чтобы просмотреть статью в базе знаний Майкрософт:
892730 Как кодировать и декодировать вложение файла программным способом с помощью Visual C# в InfoPath
Дополнительная информация
Корпорация Майкрософт предлагает примеры программного кода только для иллюстрации и не предоставляет явных или подразумеваемых гарантий относительно их корректной работы в конкретных случаях и в пользовательских приложениях. Примеры в данной статье рассчитаны на пользователя, имеющего достаточный уровень знаний соответствующего языка программирования, а также необходимых средств разработки и отладки. Специалисты служб технической поддержки Майкрософт могут пояснить назначение тех или иных конструкций кода в конкретном примере, но модификация примеров и их адаптация к задачам разработчика не поддерживается.
В следующем примере вы выполните следующие действия:
- Создайте форму, включаемую проект Visual C#.
- Создайте кодировщик.
- Создайте декодеркласс.
- Измените форму для вызова кода.
- Протестируйте операции с кодом в форме.
Создание формы, включаемой в проект Visual C#.
Создайте шаблон формы и проект, используя указания для версии InfoPath, которую вы используете.
InfoPath 2010
- В infoPath Designer создайте пустой шаблон формы и щелкните значок "Сохранить".
- При появлении запроса введите имя файла и нажмите кнопку "Сохранить".
- Откройте вкладку **Разработчик **, а затем выберите "Язык".
- В разделе "Язык кода шаблона формы" выберите C#, а затем нажмите кнопку "ОК".
InfoPath 2007
- В меню **Файл **щелкните "Конструктор шаблона формы".
- В области задач **Конструктор шаблона формы **нажмите кнопку " Пусто" и нажмите кнопку " ОК".
- В меню Файл выберите пункт Сохранить.
- При появлении запроса введите имя файла InfoPathAttachmentEncoding и нажмите кнопку "Сохранить".
- В меню Сервис выберите пункт Параметры формы.
- В разделе "Категория " в диалоговом окне **Параметры формы **нажмите кнопку " Программирование".
- В разделе "Язык программирования" в списке языков кода шаблона формы выберите C#, а затем нажмите кнопку " ОК".
Создание класса кодировщика
Создайте кодировщик, используя указания для версии InfoPath, которую вы используете.
InfoPath 2010
- На вкладке "Разработчик" щелкните **Редактор кода **, чтобы запустить редактор Visual Studio Tools for Applications (VSTA).
- В меню "Проект " щелкните "Добавить новый элемент".
- Щелкните, чтобы выбрать класс.
- В поле "Имя " измените имя на InfoPathAttachmentEncoder.cs и нажмите кнопку "Сохранить".
- В окне кода замените существующий код кодом из следующего раздела "Кодировщик".
InfoPath 2007
- Запустите редактор Visual Studio Tools for Applications (VSTA).
- В области **Обозреватель проектов **щелкните правой кнопкой мыши InfoPathAttachmentEncoding, выберите команду " Добавить" и нажмите кнопку "Создать элемент".
- В разделе "Шаблоны " выберите "Класс", измените имя на InfoPathAttachmentEncoder.cs и нажмите кнопку "Добавить".
- В окне кода вставьте код из следующего раздела "Кодировщика".
Код кодировщика
Используйте следующий код в InfoPath 2010 или InfoPath 2007:
using System;
using System.IO;
using System.Text;
using System.Security.Cryptography;
using InfoPathAttachmentEncoding;
namespace InfoPathAttachmentEncoding
{
/// <summary>
/// InfoPathAttachment encodes file data into the format expected by InfoPath for use in file attachment nodes.
/// </summary>
public 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
Создайте класс Decoderclass, используя указания для версии InfoPath, которую вы используете.
InfoPath 2010
- В редакторе кода в меню "Проект " щелкните "Добавить новый элемент", а затем выберите " Класс".
- В поле "Имя " измените имя на InfoPathAttachmentDecoder.cs и нажмите кнопку "Сохранить".
- В окне кода замените существующий код кодом из следующего раздела "Код декодера".
InfoPath 2007
- В VSTA в области **Обозреватель проектов **щелкните правой кнопкой мыши InfoPathAttachmentEncoding, нажмите кнопку "Добавить" и выберите команду "Создать элемент".
- В разделе "Шаблоны " выберите "Класс", измените имя на InfoPathAttachmentDecoder.cs и нажмите кнопку "Добавить".
- В окне кода вставьте код из следующего раздела "Код декодера".
Код декодера
Используйте следующий код в InfoPath 2010 или InfoPath 2007:
using System;
using System.IO;
using System.Text;
namespace InfoPathAttachmentEncoding
{
/// <summary>
/// Decodes a file attachment and saves it to a specified path.
/// </summary>
public 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; }
}
}
}
Изменение формы
Добавьте элемент управления "Вложение файла", элемент управления "Текстовое поле" и элемент управления "Кнопка" в форму InfoPath. Для этого выполните следующие действия:
Откройте область задач "Элементы управления", используя указания для версии InfoPath, которую вы используете.
- InfoPath 2010:В шаблоне формы InfoPathAttachmentEncoding InfoPath на вкладке **Главная *** разверните коллекцию **Controls **.
- InfoPath 2007:В шаблоне формы InfoPathAttachmentEncoding InfoPath щелкните "Элементы управления" в области задач **Задачи проектирования **.
Добавьте элемент управления "Вложение файла" в форму InfoPath, используя указания для версии InfoPath, которую вы используете:
- InfoPath 2010: в области задач " Элементы управления" в разделе " Объекты" щелкните " Вложение файла".
- InfoPath 2007: в области задач "Элементы управления" в разделе "Файл и рисунок" щелкните "Вложение файла".
Щелкните правой кнопкой мыши элемент управления **Вложение файла **, а затем выберите пункт "Свойства вложения файла".
В диалоговом окне **Свойства вложения файла **введите поле **Имя поля**, а затем нажмите кнопку "ОК ".
Добавьте элемент управления Text Box в форму InfoPath, используя указания для версии InfoPath, которую вы используете:
- InfoPath 2010: в области задач " Элементы управления" в разделе " Ввод" щелкните "Текстовое поле".
- InfoPath 2007: в области задач " Элементы управления" в разделе "Стандартный " щелкните "Текстовое поле".
Щелкните правой кнопкой мыши элемент управления "Текстовое поле" и выберите пункт " Свойства текстового поля".
В диалоговом окне **Свойства текстового поля **введите "Имя_объекта" в поле **Имя поля **, а затем нажмите кнопку "ОК ".
Добавьте кнопку "Вложить" в форму InfoPath, используя указания для версии InfoPath, которую вы используете:
- InfoPath 2010: в области задач " Элементы управления " в разделе "Объекты" нажмите кнопку.
- InfoPath 2007: в области задач " Элементы управления " в разделе "Стандартный" нажмите кнопку.
Щелкните правой кнопкой мыши новый элемент управления "Кнопка" и выберите пункт "Свойства кнопки".
В диалоговом окне **Свойства кнопки **введите Attach в поле **Метка **, введите btnAttach в поле "Идентификатор" и нажмите кнопку "Изменить код формы".
Перейдите в верхнюю часть окна кода и добавьте следующую строку кода:
using InfoPathAttachmentEncoding;
Вернитесь к фразе "Написание кода здесь", а затем добавьте следующий код:
//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()); }
Добавление кнопки "Сохранить" в форму InfoPath
Вернитесь к шаблону формы InfoPathAttachmentEncoding.
Добавьте кнопку "Сохранить", используя указания для версии InfoPath, которую вы используете:
- InfoPath 2010: в области задач " Элементы управления " в разделе "Объекты" нажмите кнопку.
- InfoPath 2007: в области задач " Элементы управления " в разделе "Стандартный" нажмите кнопку.
Щелкните правой кнопкой мыши новый элемент управления "Кнопка" и выберите пункт "Свойства кнопки".
В диалоговом окне **Свойства кнопки **введите "Сохранить" в поле **Метка **, введите btnSave в поле **Идентификатор **, а затем нажмите кнопку "Изменить код формы ".
Вставьте следующий код:
//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); //Obtain the text of the node. string theAttachment = xnAttNode.Value; if(theAttachment.Length > 0) { InfoPathAttachmentDecoder myDecoder = new InfoPathAttachmentDecoder(theAttachment); myDecoder.SaveAttachment(@"Path to the folder to save the attachment"); }
Примечание.
В этом коде замещающий путь к папке для сохранения вложения содержит расположение, в котором нужно сохранить файл.
Щелкните значок "Сохранить" и закройте VSTA.
Тестирование формы
Прежде чем эта форма сможет вложить файл, шаблон формы InfoPath должен быть полностью доверенным. Чтобы убедиться в этом, выполните одно из следующих действий:
- Используйте сертификат подписи кода для цифровой подписи файла шаблона формы (XSN). При этом пользователям предлагается доверять форме при открытии формы. Это делает форму полностью доверенной. Таким образом, для кода Visual C# предоставляются разрешения на полное доверие.
- Создайте устанавливаемый шаблон.
Убедився, что шаблон формы является полностью доверенным, его следует протестировать. Для этого выполните следующие действия:
Откройте форму в режиме предварительного просмотра, выполнив действия для версии InfoPath, которую вы используете:
- На вкладке "Главная" InfoPath 2010 нажмите кнопку "Предварительный просмотр".
- InfoPath 2007 на панели Standardtoolbar нажмите кнопку "Предварительный просмотр".
В форме InfoPath введите путь к файлу, который требуется вложить в текстовое поле, и нажмите кнопку " Вложить".
Примечание Дважды щелкните элемент управления "Вложение файла", чтобы убедиться, что файл закодирован правильно.
Щелкните Сохранить.
Найдите путь, указанный в коде раздела "Добавление кнопки "Сохранить" в форму InfoPath, а затем убедитесь, что файл сохранен в этой папке.
Нажмите кнопку "Закрыть предварительный просмотр". Это приводит к завершению теста.