Como codificar e descodificar um anexo de ficheiro através de programação através do Visual C# no InfoPath 2003

Resumo

No Microsoft Office InfoPath 2007 ou no Microsoft Office InfoPath 2003 Service Pack 1 (SP1), pode utilizar um controlo de Anexo de Ficheiro para anexar um ficheiro ao modelo de formulário do InfoPath. Em circunstâncias específicas, poderá querer codificar e, em seguida, descodificar o ficheiro anexado ao controlo Anexo de Ficheiro. Neste caso, pode utilizar o Microsoft Visual C# para criar uma turma Encoder e uma turma Decoder. Em seguida, pode utilizar a classe Codificador e a classe Decoder para codificar e descodificar o anexo de ficheiro.

Introdução

Este artigo apresenta como codificar e descodificar um ficheiro através de programação através do Microsoft Visual C# no InfoPath 2003. Para obter informações sobre como fazê-lo no InfoPath 2010 ou no InfoPath 2007, consulte a página Web seguinte: Como codificar e descodificar um anexo de ficheiro através de programação através do Visual C# no InfoPath 2010 ou no InfoPath 2007 .

Mais Informações

A Microsoft fornece exemplos de programação apenas a título informativo, sem qualquer garantia expressa ou implícita, incluindo, sem limitações, as garantias implícitas de comercialização e/ou adequação a um fim específico. Este artigo pressupõe que o utilizador está familiarizado com a linguagem de programação demonstrada e as ferramentas utilizadas para criar e depurar procedimentos. Os técnicos de suporte da Microsoft podem ajudar a explicar a funcionalidade de um determinado procedimento, mas não modificarão estes exemplos para proporcionarem funcionalidades adicionais nem criarão procedimentos adaptados às suas necessidades específicas.

Criar um projeto do Visual C# InfoPath 2003

  1. Inicia o Microsoft Visual Studio .NET 2003.

  2. No menu Ficheiro , clique em Novo e, em seguida, clique em Projeto.

  3. Na caixa de diálogo Novo Projeto, clique em Projetos Visuais C# na pasta Projetos do Microsoft Office InfoPath.

  4. Na caixa Nome , escreva AnexoEncoding e, em seguida, clique em OK.

  5. No Assistente de Projetos do Microsoft Office, clique em Criar um novo modelo de formulário e, em seguida, clique em Concluir.

    O Assistente de Projetos do Microsoft Office cria um novo projeto do Visual Studio .NET 2003 com o nome AnexoEncoding. Também é criado um modelo de formulário do InfoPath. O modelo de formulário do InfoPath é denominado AnexoEncoding.

Criar uma turma de Codificação no Visual Studio .NET 2003

  1. No Explorador de Soluções, clique com o botão direito do rato em AnexoEncoding, aponte para Adicionar e, em seguida, clique em Adicionar Novo Item.
  2. Na caixa de diálogo Adicionar Novo Item, clique em Turma no painel Modelo, escreva InfoPathAttachmentEncoder.cs na caixa Nome e, em seguida, clique em Abrir.
  3. Substitua todo o código no ficheiro InfoPathAttachmentEncoder.cs pelo seguinte código.
    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());
    }
    }
    }
    

Criar uma turma de Descodificar no Visual Studio .NET 2003

  1. No Explorador de Soluções, clique com o botão direito do rato em AnexoEncoding, aponte para Adicionar e, em seguida, clique em Adicionar Novo Item.
  2. Na caixa de diálogo Adicionar Novo Item, clique em Turma no painel Modelo, escreva InfoPathAttachmentDecoder.cs na caixa Nome e, em seguida, clique em Abrir.
  3. Substitua todo o código no ficheiro InfoPathAttachmentDecoder.cs pelo seguinte código.
    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; }
    }
    }
    }
    
    

Adicionar um controlo de Anexo de Ficheiro e um controlo de Caixa de Texto ao formulário do InfoPath

  1. No modelo de formulário anexoEncoding do InfoPath, clique em Controlos no painel de tarefas De estrutura .
  2. No painel de tarefas Controlos, clique em Anexo de Ficheiro em Controlos de Inserção.
  3. Clique com o botão direito do rato no controlo Anexo de Ficheiro e, em seguida, clique em Propriedades de Anexo de Ficheiro.
  4. Na caixa de diálogo Propriedades de Anexo de Ficheiro, escreva CampoAttachment na caixa Nome do Campo e, em seguida, clique em OK.
  5. No painel de tarefas Controlos , clique em Caixa de Texto em Inserir controlos.
  6. Clique com o botão direito do rato no controlo Caixa de Texto e, em seguida, clique em Propriedades da Caixa de Texto.
  7. Na caixa de diálogo Propriedades da Caixa de Texto, escreva NomeDoAttachment na caixa Nome do Campo e, em seguida, clique em OK.

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

  1. No painel de tarefas Controlos, clique em Botão em Inserir controlos.
  2. Clique com o botão direito do rato no novo controlo de Botão e, em seguida, clique em Propriedades do Botão.
  3. Na caixa de diálogo Propriedades do Botão, escreva Anexar na caixa Etiqueta, escreva btnAttach na caixa ID e, em seguida, clique em Editar Código de Formulário.
  4. Adicione o seguinte código ao método btnAttach_OnClick base.
    //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();
    }
    
    

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

  1. Mudar para o modelo de formulário do InfoPath anexoEncoding.
  2. No painel de tarefas Controlos, clique em Botão em Inserir controlos.
  3. Clique com o botão direito do rato no novo controlo de Botão e, em seguida, clique em Propriedades do Botão.
  4. Na caixa de diálogo Propriedades do Botão, escreva Guardar na caixa Etiqueta, escreva btnSave na caixa ID e, em seguida, clique em Editar Código de Formulário.
  5. Adicione o seguinte código ao método de _OnClick btnSave.
    //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>");
    }
    
    

Nota

Neste código, substitua pela localização onde pretende guardar o ficheiro.

Certificar-se de que o modelo de formulário do InfoPath é totalmente fiável

Antes de poder testar este formulário, o modelo de formulário do InfoPath tem de ser totalmente fiável. Pode utilizar um dos seguintes métodos para se certificar de que o modelo de formulário do InfoPath é totalmente fiável:

  • Utilize o utilitário de Configuração do Microsoft .NET Framework 1.1 para conceder permissões de Confiança Total apenas ao seu código Visual C#.

  • Utilize o utilitário RegForm do InfoPath Software Development Kit (SDK) para tornar o formulário totalmente fidediável. Isto concede permissões de Confiança Total ao seu código Visual C#.

  • Utilize um certificado de assinatura de código para assinar digitalmente o ficheiro de modelo de formulário (.xsn). Quando utiliza um certificado de assinatura de código para assinar digitalmente o ficheiro de modelo de formulário, os utilizadores são obrigados a confiar no formulário quando abrem o formulário. Isto torna o formulário totalmente fiável. Portanto, as permissões de Confiança Total são concedidas ao seu código Visual C#.

  • Utilize a macro IPFullTrust do SDK do InfoPath para tornar o formulário um formulário totalmente confiável. A macro IPFullTrust automatiza a definição do ficheiro de manifesto (.xsf) e do ficheiro de modelo de formulário no projeto do InfoPath para uma confiança total e, em seguida, a macro IPFullTrust regista automaticamente o modelo de formulário.

    Para obter mais informações sobre como instalar e utilizar a macro, visite o seguinte Web site do Microsoft Developer Network (MSDN):

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

  • Utilize a Automatização Externa no InfoPath para chamar o método RegisterSolution. Normalmente, este método só é utilizado para o desenvolvimento de formulários porque um formulário registado só se regista num computador individual. Para quaisquer formulários adicionais, os outros utilizadores têm de registar os formulários adicionais nos respetivos computadores. Não recomendamos este método para formulários adicionais. Recomendamos qualquer um dos métodos anteriores quando publicar o formulário.

Uma vez que este formulário está em desenvolvimento de formulários, pode utilizar o último método. Para tal, localize o modelo de formulário do AttachmentEncoding InfoPath e, em seguida, siga estes passos:

  1. No menu Ferramentas , clique em Opções de Formulário.

  2. Clique no separador Segurança.

  3. Clique para desmarcar a caixa de verificação Determinar automaticamente o nível de segurança com base na estrutura (recomendada) do formulário.

    Nota O InfoPath não consegue detetar automaticamente lógica empresarial que requer permissões de Confiança Total. Assim, tem de conceder explicitamente permissões de Confiança Total.

  4. Clique em Confiança Total e, em seguida, clique em OK.

  5. Feche o modelo de formulário do InfoPath anexoEncoding. Se lhe for pedido para guardar as alterações, clique em Sim.

    Nota Não feche o projeto Visual Studio .NET 2003.

  6. No Visual Studio .NET 2003, faça duplo clique no ficheiro Manifest.xsf no Explorador de Soluções. O ficheiro Manifest.xsf é aberto.

  7. No nó raiz, localize o atributo publishUrl. Remova o atributo publishUrl e o valor do atributo publishUrl.

  8. Guarde as suas alterações e, em seguida, feche o ficheiro Manifest.xsf.

  9. Clique em Iniciar, clique em Executar, escreva bloco de notas e, em seguida, clique em OK.

  10. Adicione o seguinte código ao ficheiro de texto em branco.

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

    Nota Neste código, substitua o project_folder_url pelo caminho do ficheiro Manifest.xsf na pasta do projeto. Lembre-se de sair do caminho do ficheiro Manifest.xsf. Todas as barras inversas (\) únicas no caminho têm de ser substituídas por duas barras inversas (\\).

  11. Guarde o ficheiro Manifest.xsf no computador como o Register.js ficheiro.

  12. Para chamar o método RegisterSolution, faça duplo clique Register.js ficheiro que criou.

Testar o formulário

  1. No projeto AttachmentEncoding Visual Studio .NET 2003, clique em Iniciar no menu Depurar . Esta ação inicia o formulário do InfoPath no modo de Pré-visualização.

  2. No formulário do InfoPath, escreva o caminho do ficheiro que pretende anexar na caixa de texto e, em seguida, clique em Anexar.

    Nota Faça duplo clique no controlo Anexo de Ficheiro para verificar se o ficheiro está codificado corretamente.

  3. Clique em Guardar. Localize o caminho fornecido na secção "Adicionar um botão Guardar ao formulário do InfoPath".

  4. Para terminar o teste, clique em Fechar Pré-visualização.

Referências

Para obter mais informações sobre o formato de cabeçalho de anexo de ficheiro, visite o seguinte site do MSDN:

Anexar ficheiros no InfoPath 2003 https://msdn.microsoft.com/en-us/library/aa168351(office.11).aspx