Como codificar e decodificar um anexo de arquivo programaticamente usando o Visual C# no InfoPath 2010 ou no InfoPath 2007

Resumo

No Microsoft InfoPath 2010 ou no Microsoft Office InfoPath 2007, você pode usar um controle anexo de arquivo para anexar um arquivo ao modelo de formulário do InfoPath. Em circunstâncias específicas, talvez você queira codificar e, em seguida, decodificar o arquivo anexado ao controle Anexo de Arquivo. Nesse caso, você pode usar o Microsoft Visual C# para criar uma Encoderclass e uma Decoderclass. Em seguida, você pode usar o Encoderclass e o Decoderclass para codificar e decodificar o anexo de arquivo. Este artigo descreve como criar um modelo de formulário do InfoPath que codifica um arquivo para anexo no formulário e decodifica o anexo para salvar no sistema de arquivos.  

Para obter mais informações sobre como fazer isso no InfoPath 2003, clique no seguinte número de artigo para exibir o artigo na Base de Dados de Conhecimento Microsoft:

892730 Como codificar e decodificar um anexo de arquivo programaticamente usando o Visual C# no InfoPath

Informações adicionais

A Microsoft fornece exemplos de programação apenas para fins ilustrativos, sem garantia explícita ou implícita, incluindo, mas sem se limitar a, garantias de comercialização e/ou adequação para uma finalidade específica. Este artigo pressupõe que você conhece a linguagem de programação demonstrada e as ferramentas usadas para criar e depurar os procedimentos. A equipe de suporte da Microsoft pode ajudar a explicar a funcionalidade de um determinado procedimento, mas não modificará estes exemplos para fornecer funcionalidades adicionais ou construir procedimentos a fim de atender às necessidades específicas.

No exemplo a seguir, você seguirá estas etapas:

  1. Crie um formulário que inclua um projeto do Visual C#.
  2. Crie uma Encoderclass.
  3. Crie um Decoderclass.
  4. Modifique o formulário para chamar o código.
  5. Teste as operações de código no formulário.

Criar um formulário que inclui um projeto do Visual C#

Crie um modelo de formulário e um projeto usando as instruções para a versão do InfoPath que você está usando.

InfoPath 2010

  1. No InfoPath Designer, crie um modelo de formulário em branco e clique no ícone Salvar.
  2. Quando for solicitado, digite o nome do arquivo e clique em Salvar.
  3. Clique na guia **Desenvolvedor ** e clique em Idioma.
  4. Em Linguagem de código do modelo de formulário, selecione C# e clique em OK.

InfoPath 2007

  1. No menu **Arquivo **, clique em Criar um Modelo de Formulário.
  2. No painel de tarefas **Criar um Modelo de Formulário**, clique em Branco e clique em OK.
  3. No menu Arquivo, clique em Salvar.
  4. Quando for solicitado, digite o nome de arquivo InfoPathAttachmentEncoding e clique em Salvar.
  5. No menu Ferramentas , clique em Opções de Formulário.
  6. Em Categoria na caixa de diálogo **Opções de Formulário **, clique em Programação.
  7. Em Linguagem de programação, na lista de linguagens de código do modelo de formulário, selecione C# e clique em OK.

Criar uma classe de codificador

Crie uma Encoderclass usando as instruções para a versão do InfoPath que você está usando.

InfoPath 2010

  1. Na guia Desenvolvedor, clique em **Editor de Código **para iniciar o editor Visual Studio Tools for Applications (VSTA).
  2. No menu Projeto , clique em Adicionar Novo Item.
  3. Clique para selecionar Classe.
  4. No campo Nome , altere o nome para InfoPathAttachmentEncoder.cs e clique em Salvar.
  5. Na janela de código, substitua o código existente pelo código da seção "Código codificador" a seguir.

InfoPath 2007

  1. Inicie o editor Visual Studio Tools for Applications (VSTA). 
  2. No painel **Explorador de Projetos **, clique com o botão direito do mouse em InfoPathAttachmentEncoding, clique em Adicionar e emNovo Item.
  3. Na seção Modelos , selecione Classe, altere o nome para InfoPathAttachmentEncoder.cs e clique em Adicionar.
  4. Na janela de código, cole o código da seção "Código do codificador" a seguir.

Código do codificador

Use o seguinte código no InfoPath 2010 ou no 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());
}
}
}

Criar uma classe de decodificador

Crie uma Decoderclass usando as instruções para a versão do InfoPath que você está usando.

InfoPath 2010

  1. No Editor de Códigos, no menu Projeto , clique em Adicionar Novo Item e, em seguida, clique para selecionar Classe.
  2. No campo Nome , altere o nome para InfoPathAttachmentDecoder.cs e clique em Salvar.
  3. Na janela de código, substitua o código existente pelo código da seção "Código do decodificador" a seguir. 

InfoPath 2007

  1. No VSTA, no painel **Explorador de Projetos **, clique com o botão direito do mouse em InfoPathAttachmentEncoding, clique em Adicionar e emNovo Item.
  2. Na seção Modelos , selecione Classe, altere o nome para InfoPathAttachmentDecoder.cs e clique em Adicionar.
  3. Na janela de código, cole o código da seção "Código do decodificador" a seguir.

Código do decodificador

Use o seguinte código no InfoPath 2010 ou no 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; }
}
}
}

Modificar o formulário

Adicione um controle Anexo de Arquivo, um controle Caixa de Texto e um controle Button ao formulário do InfoPath. Para fazer isso, siga estas etapas:

  1. Abra o painel de tarefas Controles usando as instruções para a versão do InfoPath que você está usando. 

    • InfoPath 2010:No modelo de formulário InfoPathAttachmentEncoding InfoPath, na guia **Página Inicial**, expanda a galeria **Controles **.
    • InfoPath 2007:No modelo de formulário InfoPathAttachmentEncoding InfoPath, clique em Controles no painel de tarefas **Tarefas de Design **.
  2. Adicione um controle Anexo de Arquivo ao formulário do InfoPath usando as instruções para a versão do InfoPath que você está usando:

    • InfoPath 2010: No painel de tarefas Controles , em Objetos, clique em Anexo de Arquivo.
    • InfoPath 2007: No painel de tarefas Controles , em Arquivo e Imagem, clique em Anexo de Arquivo.
  3. Clique com o botão direito do mouse no controle **Anexo de Arquivo **e clique em Propriedades do Anexo de Arquivo.

  4. Na caixa de diálogo **Propriedades do Anexo de Arquivo **, digite theAttachmentFieldin na caixa **Nome do Campo *** e clique em OK.

  5. Adicione um controle Caixa de Texto ao formulário do InfoPath usando as instruções para a versão do InfoPath que você está usando:

    • InfoPath 2010: No painel de tarefas Controles , em Entrada, clique em Caixa de Texto.
    • InfoPath 2007: No painel de tarefas Controles , em Padrão, clique em Caixa de Texto.
  6. Clique com o botão direito do mouse no controle Caixa de Texto e clique em Propriedades da Caixa de Texto.

  7. Na caixa de diálogo **Propriedades da Caixa de Texto **, digite theAttachmentName na caixa **Nome do Campo **e clique em OK.

  8. Adicione um botão Anexar ao formulário do InfoPath usando as instruções para a versão do InfoPath que você está usando:

    • InfoPath 2010: No painel de tarefas Controles , em Objetos, clique em Botão.
    • InfoPath 2007: No painel de tarefas Controles , em Padrão, clique em Botão.
  9. Clique com o botão direito do mouse no novo controle Botão e clique em Propriedades do Botão.

  10. Na caixa de diálogo **Propriedades do Botão **, digite Anexar na caixa **Rótulo **, digite btnAttach na caixa ID e clique em Editar Código de Formulário.

  11. Vá para a parte superior da janela de código e adicione a seguinte linha de código:

    using InfoPathAttachmentEncoding;
    
  12. Retorne para "escrever seu código aqui" e adicione o seguinte código:

     //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());
     }              
    
    

Adicionar um botão Salvar ao formulário do InfoPath

  1. Retorne ao modelo de formulário InfoPathAttachmentEncoding.

  2. Adicione um botão Salvar usando as instruções para a versão do InfoPath que você está usando:

    • InfoPath 2010: No painel de tarefas Controles , em Objetos, clique em Botão.
    • InfoPath 2007: No painel de tarefas Controles , em Padrão, clique em Botão.
  3. Clique com o botão direito do mouse no novo controle Botão e clique em Propriedades do Botão.

  4. Na caixa de diálogo **Propriedades do Botão **, digite Salvar na caixa **Rótulo **, digite btnSave na caixa **ID ** e clique em Editar Código de Formulário.

  5. Insira o seguinte código:

     //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");
     }                                              
    
    

Observação

Nesse código, o caminho do espaço reservado para a pasta para salvar o anexo representa o local no qual você deseja salvar o arquivo.

Clique no ícone Salvar e feche o VSTA.

Testar o formulário

Antes que esse formulário possa anexar um arquivo, o modelo de formulário do InfoPath deve ser totalmente confiável. Para garantir isso, execute uma das seguintes ações:

  • Use um certificado de assinatura de código para assinar digitalmente o arquivo de modelo de formulário (.xsn). Quando você fizer isso, os usuários serão solicitados a confiar no formulário quando abrirem o formulário. Isso torna o formulário totalmente confiável. Portanto, as permissões de Confiança Total são concedidas ao código do Visual C#.
  • Crie um modelo inserível.

Depois de verificar se o modelo de formulário é totalmente confiável, você deve testá-lo. Para fazer isso, siga estas etapas:

  1. Abra o formulário no modo de visualização seguindo as etapas para a versão do InfoPath que você está usando:

    • InfoPath 2010 Na guia Página Inicial, clique em Visualizar.
    • InfoPath 2007 Na barra standardtool, clique em Visualizar.
  2. No formulário do InfoPath, digite o caminho do arquivo que você deseja anexar na caixa de texto e clique em Anexar.

    Nota Clique duas vezes no controle Anexo de Arquivo para verificar se o arquivo está codificado corretamente. 

  3. Clique em Salvar.

  4. Localize o caminho fornecido no código para a seção "Adicionar um botão Salvar ao formulário do InfoPath" e verifique se o arquivo foi salvo nessa pasta. 

  5. Clique em Fechar Visualização. Isso encerra o teste.