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

Аннотация

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

Введение

В этой статье описывается, как кодировать и декодировать вложение файла программным способом с помощью Microsoft Visual C# в InfoPath 2003. Сведения о том, как это сделать в InfoPath 2010 или InfoPath 2007, см. на следующей веб-странице: как кодировать и декодировать вложение файла программным способом с помощью Visual C# в InfoPath 2010 или InfoPath 2007 .

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

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

Создание проекта InfoPath 2003 для Visual C#

  1. Запустите Microsoft Visual Studio .NET 2003.

  2. В меню Файл выберите команду Создать, а затем выберите Проект.

  3. В диалоговом окне "Новый проект" в папке Microsoft Office InfoPath Projects щелкните "Проекты Visual C #".

  4. В поле "Имя " введите AttachmentEncoding и нажмите кнопку " ОК".

  5. В мастере проектов Microsoft Office щелкните "Создать новый шаблон формы" и нажмите кнопку " Готово".

    Мастер проектов Microsoft Office создает проект Visual Studio .NET 2003 с именем AttachmentEncoding. Также создается шаблон формы InfoPath. Шаблон формы InfoPath называется AttachmentEncoding.

Создание класса кодировщика в Visual Studio .NET 2003

  1. В Обозреватель решений щелкните правой кнопкой мыши AttachmentEncoding, наведите указатель мыши на пункт "Добавить" и выберите команду "Добавить новый элемент".
  2. В диалоговом окне "Добавление нового элемента" щелкните "Класс" в области "Шаблон", введите InfoPathAttachmentEncoder.cs в поле "Имя" и нажмите кнопку "Открыть".
  3. Замените весь код в файле InfoPathAttachmentEncoder.cs следующим кодом.
    using System;
    using System.IO;
    using System.Text;
    using System.Security.Cryptography;
    
    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();
    
    // Get 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 в Visual Studio .NET 2003

  1. В Обозреватель решений щелкните правой кнопкой мыши AttachmentEncoding, наведите указатель мыши на пункт "Добавить" и выберите команду "Добавить новый элемент".
  2. В диалоговом окне "Добавление нового элемента" щелкните "Класс" в области "Шаблон", введите InfoPathAttachmentDecoder.cs в поле "Имя", а затем нажмите кнопку "Открыть".
  3. Замените весь код в файле InfoPathAttachmentDecoder.cs следующим кодом.
    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 get 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))
    {
    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 AttachmentEncoding щелкните " Элементы управления " в области задач "Задачи проектирования".
  2. В области задач "Элементы управления" щелкните " Вложение файла" в разделе элементов управления "Вставка".
  3. Щелкните правой кнопкой мыши элемент управления "Вложение файла" и выберите пункт "Свойства вложения файла".
  4. В диалоговом окне "Свойства вложения файла" введите поле "Имя поля" и нажмите кнопку "ОК".
  5. В области задач " Элементы управления" щелкните " Текстовое поле" в разделе элементов управления "Вставка".
  6. Щелкните правой кнопкой мыши элемент управления "Текстовое поле " и выберите пункт " Свойства текстового поля".
  7. В диалоговом окне "Свойства текстового поля" введите "AttachmentName" в поле "Имя поля" и нажмите кнопку "ОК".

Добавление кнопки "Вложить" в форму InfoPath

  1. В области задач " Элементы управления" нажмите кнопку "Кнопка" в разделе "Вставить элементы управления".
  2. Щелкните правой кнопкой мыши новый элемент управления " Кнопка" и выберите пункт "Свойства кнопки".
  3. В диалоговом окне "Свойства кнопки" введите "Присоединить" в поле "Метка", введите btnAttach в поле "Идентификатор" и нажмите кнопку "Изменить код формы".
  4. Добавьте следующий код в метод btnAttach_OnClick.
    //Get a reference to the attachment node.
    IXMLDOMNode theAttachmentNode = thisXDocument.DOM.selectSingleNode("my:myFields/my:theAttachmentField");
    
    //Get a reference to the filename node.
    IXMLDOMNode fileNameNode = thisXDocument.DOM.selectSingleNode("my:myFields/my:theAttachmentName");
    //Get the text of the node.
    String fileName = fileNameNode.text;
    if(fileName.Length > 0)
    {
    //Encode the file and assign it to the attachment node.
    InfoPathAttachmentEncoding.Encoder myEncoder = new InfoPathAttachmentEncoding.Encoder(fileName);
    if(theAttachmentNode.attributes.getNamedItem("xsi:nil") != null)
    theAttachmentNode.attributes.removeNamedItem("xsi:nil");
    theAttachmentNode.text = myEncoder.ToBase64String();
    }
    
    

Добавление кнопки "Сохранить" в форму InfoPath

  1. Переключитесь на шаблон формы InfoPath AttachmentEncoding.
  2. В области задач " Элементы управления" нажмите кнопку "Кнопка" в разделе "Вставить элементы управления".
  3. Щелкните правой кнопкой мыши новый элемент управления " Кнопка" и выберите пункт "Свойства кнопки".
  4. В диалоговом окне "Свойства кнопки" введите "Сохранить" в поле "Метка", введите btnSave в поле "Идентификатор" и нажмите кнопку "Изменить код формы".
  5. Добавьте следующий код в метод btnSave _OnClick.
    //Get a reference to the attachment node.
    IXMLDOMNode n = thisXDocument.DOM.selectSingleNode("my:myFields/my:theAttachmentField");
    //Get the text of the node.
    String theAttachment = n.text;
    if(theAttachment.Length > 0)
    {
    InfoPathAttachmentEncoding.Decoder myDecoder = new InfoPathAttachmentEncoding.Decoder(theAttachment);
    myDecoder.SaveAttachment(@"<Path to save the file>");
    }
    
    

Примечание.

В этом коде замените расположение, в котором нужно сохранить файл.

Убедитесь, что шаблон формы InfoPath является полностью доверенным

Прежде чем вы сможете протестировать эту форму, шаблон формы InfoPath должен быть полностью доверенным. Чтобы убедиться, что шаблон формы InfoPath является полностью доверенным, можно использовать один из следующих методов:

  • Используйте служебную программу конфигурации Microsoft платформа .NET Framework 1.1, чтобы предоставить разрешения на полное доверие только коду Visual C#.

  • Используйте служебную программу RegForm из пакета SDK для InfoPath, чтобы сделать форму полностью доверенной. Это предоставляет разрешения на полное доверие для кода Visual C#.

  • Используйте сертификат подписи кода для цифровой подписи файла шаблона формы (XSN). При использовании сертификата подписи кода для цифровой подписи файла шаблона формы пользователям предлагается доверять форме при открытии формы. Это делает форму полностью доверенной. Таким образом, для кода Visual C# предоставляются разрешения на полное доверие.

  • Используйте макрос IPFullTrust из пакета SDK InfoPath, чтобы сделать форму полностью доверенной. Макрос IPFullTrust автоматизирует настройку файла манифеста (XSF) и файла шаблона формы в проекте InfoPath для полного доверия, а затем макрос IPFullTrust автоматически регистрирует шаблон формы.

    Дополнительные сведения об установке и использовании макроса см. на следующем веб-сайте Microsoft Developer Network (MSDN):

    https://msdn.microsoft.com/en-us/library/aa202736(office.11).aspx

  • Используйте внешнюю автоматизацию в InfoPath для вызова метода RegisterSolution. Как правило, этот метод используется только для разработки форм, так как зарегистрированная форма регистрируется только для отдельного компьютера. Для любых дополнительных форм другие пользователи должны зарегистрировать дополнительные формы на своих компьютерах. Мы не рекомендуем использовать этот метод для дополнительных форм. При публикации формы рекомендуется использовать любой из предыдущих методов.

Так как эта форма находится на этапе разработки формы, можно использовать последний метод. Для этого найдите шаблон формы InfoPath AttachmentEncoding и выполните следующие действия:

  1. В меню Сервис выберите пункт Параметры формы.

  2. Щелкните вкладку Безопасность.

  3. Щелкните, чтобы снять флажок "Автоматически определять уровень безопасности на основе макета формы (рекомендуется )".

    Примечание InfoPath не может автоматически обнаружить бизнес-логику, которая требует разрешений на полное доверие. Поэтому необходимо явно предоставить разрешения на полное доверие.

  4. Нажмите кнопку "Полное доверие" и нажмите кнопку "ОК".

  5. Закройте шаблон формы InfoPath AttachmentEncoding. Если вам будет предложено сохранить изменения, нажмите кнопку "Да".

    Примечание Не закрывайте проект Visual Studio .NET 2003.

  6. В Visual Studio .NET 2003 дважды щелкните файл Manifest.xsf в Обозреватель решений. Откроется файл Manifest.xsf.

  7. В корневом узле найдите атрибут publishUrl. Удалите атрибут publishUrl и значение атрибута publishUrl.

  8. Сохраните изменения и закройте файл Manifest.xsf.

  9. Нажмите кнопку "Пуск", нажмите кнопку "Выполнить", введите блокнот и нажмите кнопку "ОК".

  10. Добавьте следующий код в пустой текстовый файл.

    oApp = WScript.CreateObject("InfoPath.ExternalApplication");
    strAbsolutePath = "<project_folder_url>\\Manifest.xsf";
    oApp.RegisterSolution(strAbsolutePath,"overwrite"); 
    
    

    Примечание В этом коде замените project_folder_url путем к файлу Manifest.xsf в папке проекта. Не забудьте экранировать путь к файлу Manifest.xsf. Все отдельные обратные косые черты (\) в пути должны быть заменены двумя обратными косой чертой (\\).

  11. Сохраните файл Manifest.xsf на компьютере в Register.js файла.

  12. Чтобы вызвать метод RegisterSolution, дважды щелкните созданныйRegister.jsфайла.

Тестирование формы

  1. В проекте Visual Studio .NET 2003 AttachmentEncoding щелкните "Пуск " в меню "Отладка ". При этом форма InfoPath запускается в режиме предварительного просмотра.

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

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

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

  4. Чтобы завершить тест, нажмите кнопку "Закрыть предварительный просмотр".

Ссылки

Дополнительные сведения о формате заголовка вложения файла см. на следующем веб-сайте MSDN:

Вложение файлов в InfoPath 2003 https://msdn.microsoft.com/en-us/library/aa168351(office.11).aspx