Как кодировать и декодировать вложение файла программным способом с помощью Visual C# в InfoPath 2010 или InfoPath 2007

Аннотация

В Microsoft InfoPath 2010, русская версия Или в Microsoft Office InfoPath 2007 можно использовать элемент управления "Вложение файла", чтобы вложить файл в шаблон формы InfoPath. В определенных обстоятельствах может потребоваться закодировать, а затем декодировать файл, присоединенный к элементу управления "Вложение файла". В этом случае для создания кодировщика и декодера можно использовать Microsoft Visual C#. Затем можно использовать кодировщик и декодировщик для кодирования и декодирования вложения файла. В этой статье описывается, как спроектировать шаблон формы InfoPath, который кодирует файл для вложения в форму и декодирует вложение для сохранения в файловой системе.  

Для получения дополнительных сведений о том, как это сделать в InfoPath 2003, щелкните следующий номер статьи, чтобы просмотреть статью в базе знаний Майкрософт:

892730 Как кодировать и декодировать вложение файла программным способом с помощью Visual C# в InfoPath

Дополнительная информация

Корпорация Майкрософт предлагает примеры программного кода только для иллюстрации и не предоставляет явных или подразумеваемых гарантий относительно их корректной работы в конкретных случаях и в пользовательских приложениях. Примеры в данной статье рассчитаны на пользователя, имеющего достаточный уровень знаний соответствующего языка программирования, а также необходимых средств разработки и отладки. Специалисты служб технической поддержки Майкрософт могут пояснить назначение тех или иных конструкций кода в конкретном примере, но модификация примеров и их адаптация к задачам разработчика не поддерживается.

В следующем примере вы выполните следующие действия:

  1. Создайте форму, включаемую проект Visual C#.
  2. Создайте кодировщик.
  3. Создайте декодеркласс.
  4. Измените форму для вызова кода.
  5. Протестируйте операции с кодом в форме.

Создание формы, включаемой в проект Visual C#.

Создайте шаблон формы и проект, используя указания для версии InfoPath, которую вы используете.

InfoPath 2010

  1. В infoPath Designer создайте пустой шаблон формы и щелкните значок "Сохранить".
  2. При появлении запроса введите имя файла и нажмите кнопку "Сохранить".
  3. Откройте вкладку **Разработчик **, а затем выберите "Язык".
  4. В разделе "Язык кода шаблона формы" выберите C#, а затем нажмите кнопку "ОК".

InfoPath 2007

  1. В меню **Файл **щелкните "Конструктор шаблона формы".
  2. В области задач **Конструктор шаблона формы **нажмите кнопку " Пусто" и нажмите кнопку " ОК".
  3. В меню Файл выберите пункт Сохранить.
  4. При появлении запроса введите имя файла InfoPathAttachmentEncoding и нажмите кнопку "Сохранить".
  5. В меню Сервис выберите пункт Параметры формы.
  6. В разделе "Категория " в диалоговом окне **Параметры формы **нажмите кнопку " Программирование".
  7. В разделе "Язык программирования" в списке языков кода шаблона формы выберите C#, а затем нажмите кнопку " ОК".

Создание класса кодировщика

Создайте кодировщик, используя указания для версии InfoPath, которую вы используете.

InfoPath 2010

  1. На вкладке "Разработчик" щелкните **Редактор кода **, чтобы запустить редактор Visual Studio Tools for Applications (VSTA).
  2. В меню "Проект " щелкните "Добавить новый элемент".
  3. Щелкните, чтобы выбрать класс.
  4. В поле "Имя " измените имя на InfoPathAttachmentEncoder.cs и нажмите кнопку "Сохранить".
  5. В окне кода замените существующий код кодом из следующего раздела "Кодировщик".

InfoPath 2007

  1. Запустите редактор Visual Studio Tools for Applications (VSTA). 
  2. В области **Обозреватель проектов **щелкните правой кнопкой мыши InfoPathAttachmentEncoding, выберите команду " Добавить" и нажмите кнопку "Создать элемент".
  3. В разделе "Шаблоны " выберите "Класс", измените имя на InfoPathAttachmentEncoder.cs и нажмите кнопку "Добавить".
  4. В окне кода вставьте код из следующего раздела "Кодировщика".

Код кодировщика

Используйте следующий код в 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

  1. В редакторе кода в меню "Проект " щелкните "Добавить новый элемент", а затем выберите " Класс".
  2. В поле "Имя " измените имя на InfoPathAttachmentDecoder.cs и нажмите кнопку "Сохранить".
  3. В окне кода замените существующий код кодом из следующего раздела "Код декодера". 

InfoPath 2007

  1. В VSTA в области **Обозреватель проектов **щелкните правой кнопкой мыши InfoPathAttachmentEncoding, нажмите кнопку "Добавить" и выберите команду "Создать элемент".
  2. В разделе "Шаблоны " выберите "Класс", измените имя на InfoPathAttachmentDecoder.cs и нажмите кнопку "Добавить".
  3. В окне кода вставьте код из следующего раздела "Код декодера".

Код декодера

Используйте следующий код в 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. Для этого выполните следующие действия:

  1. Откройте область задач "Элементы управления", используя указания для версии InfoPath, которую вы используете. 

    • InfoPath 2010:В шаблоне формы InfoPathAttachmentEncoding InfoPath на вкладке **Главная *** разверните коллекцию **Controls **.
    • InfoPath 2007:В шаблоне формы InfoPathAttachmentEncoding InfoPath щелкните "Элементы управления" в области задач **Задачи проектирования **.
  2. Добавьте элемент управления "Вложение файла" в форму InfoPath, используя указания для версии InfoPath, которую вы используете:

    • InfoPath 2010: в области задач " Элементы управления" в разделе " Объекты" щелкните " Вложение файла".
    • InfoPath 2007: в области задач "Элементы управления" в разделе "Файл и рисунок" щелкните "Вложение файла".
  3. Щелкните правой кнопкой мыши элемент управления **Вложение файла **, а затем выберите пункт "Свойства вложения файла".

  4. В диалоговом окне **Свойства вложения файла **введите поле **Имя поля**, а затем нажмите кнопку "ОК ".

  5. Добавьте элемент управления Text Box в форму InfoPath, используя указания для версии InfoPath, которую вы используете:

    • InfoPath 2010: в области задач " Элементы управления" в разделе " Ввод" щелкните "Текстовое поле".
    • InfoPath 2007: в области задач " Элементы управления" в разделе "Стандартный " щелкните "Текстовое поле".
  6. Щелкните правой кнопкой мыши элемент управления "Текстовое поле" и выберите пункт " Свойства текстового поля".

  7. В диалоговом окне **Свойства текстового поля **введите "Имя_объекта" в поле **Имя поля **, а затем нажмите кнопку "ОК ".

  8. Добавьте кнопку "Вложить" в форму InfoPath, используя указания для версии InfoPath, которую вы используете:

    • InfoPath 2010: в области задач " Элементы управления " в разделе "Объекты" нажмите кнопку.
    • InfoPath 2007: в области задач " Элементы управления " в разделе "Стандартный" нажмите кнопку.
  9. Щелкните правой кнопкой мыши новый элемент управления "Кнопка" и выберите пункт "Свойства кнопки".

  10. В диалоговом окне **Свойства кнопки **введите Attach в поле **Метка **, введите btnAttach в поле "Идентификатор" и нажмите кнопку "Изменить код формы".

  11. Перейдите в верхнюю часть окна кода и добавьте следующую строку кода:

    using InfoPathAttachmentEncoding;
    
  12. Вернитесь к фразе "Написание кода здесь", а затем добавьте следующий код:

     //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

  1. Вернитесь к шаблону формы InfoPathAttachmentEncoding.

  2. Добавьте кнопку "Сохранить", используя указания для версии InfoPath, которую вы используете:

    • InfoPath 2010: в области задач " Элементы управления " в разделе "Объекты" нажмите кнопку.
    • InfoPath 2007: в области задач " Элементы управления " в разделе "Стандартный" нажмите кнопку.
  3. Щелкните правой кнопкой мыши новый элемент управления "Кнопка" и выберите пункт "Свойства кнопки".

  4. В диалоговом окне **Свойства кнопки **введите "Сохранить" в поле **Метка **, введите btnSave в поле **Идентификатор **, а затем нажмите кнопку "Изменить код формы ".

  5. Вставьте следующий код:

     //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# предоставляются разрешения на полное доверие.
  • Создайте устанавливаемый шаблон.

Убедився, что шаблон формы является полностью доверенным, его следует протестировать. Для этого выполните следующие действия:

  1. Откройте форму в режиме предварительного просмотра, выполнив действия для версии InfoPath, которую вы используете:

    • На вкладке "Главная" InfoPath 2010 нажмите кнопку "Предварительный просмотр".
    • InfoPath 2007 на панели Standardtoolbar нажмите кнопку "Предварительный просмотр".
  2. В форме InfoPath введите путь к файлу, который требуется вложить в текстовое поле, и нажмите кнопку " Вложить".

    Примечание Дважды щелкните элемент управления "Вложение файла", чтобы убедиться, что файл закодирован правильно. 

  3. Щелкните Сохранить.

  4. Найдите путь, указанный в коде раздела "Добавление кнопки "Сохранить" в форму InfoPath, а затем убедитесь, что файл сохранен в этой папке. 

  5. Нажмите кнопку "Закрыть предварительный просмотр". Это приводит к завершению теста.