Cómo codificar y descodificar un archivo adjunto mediante programación utilizando Visual C# en InfoPath 2003

Resumen

En Microsoft Office InfoPath 2007 o en Microsoft Office InfoPath 2003 Service Pack 1 (SP1), puede utilizar un control de Datos adjuntos para adjuntar un archivo a la plantilla de formulario de InfoPath. En determinadas circunstancias, es aconsejable codificar y descodificar, a continuación, el archivo que está adjunto al control de Archivo adjunto . En este caso, puede utilizar Microsoft Visual C# para crear una clase de codificador y una clase de descodificador . A continuación, puede utilizar las clases de codificador y el descodificador para codificar y descodificar el archivo adjunto.

INTRODUCCIÓN

Este artículo presenta cómo codificar y descodificar un archivo adjunto mediante programación utilizando Microsoft Visual C# en InfoPath 2003. Para obtener información sobre cómo hacerlo en 2010 de InfoPath o en InfoPath 2007, vea la siguiente página web: cómo codificar y descodificar un archivo adjunto mediante programación usando Visual C# en 2010 de InfoPath o en InfoPath 2007 .

Más información

Microsoft proporciona ejemplos de programación únicamente con fines ilustrativos, sin ninguna garantía expresa o implícita. Esto incluye, pero no se limita, a las garantías implícitas de comerciabilidad o idoneidad para un propósito particular. Este artículo asume que está familiarizado con el lenguaje de programación que se muestra y con las herramientas que se utilizan para crear y depurar procedimientos. Los ingenieros de soporte técnico de Microsoft pueden explicarle la funcionalidad de un determinado procedimiento, pero no modificarán estos ejemplos para ofrecer mayor funcionalidad ni crearán procedimientos que cumplan sus requisitos específicos.

Crear un proyecto de Visual C# InfoPath 2003

  1. Inicie Microsoft Visual Studio .NET 2003.
  2. En el menú archivo , haga clic en
    De nuevoy, a continuación, haga clic en proyecto.
  3. En el cuadro de diálogo Nuevo proyecto , haga clic en
    Proyectos de visual C# en la carpeta de proyectos de Microsoft Office InfoPath.
  4. En el cuadro nombre , escriba
    AttachmentEncodingy, a continuación, haga clic en
    OK.
  5. En el Asistente para proyectos de Microsoft Office, haga clic en
    Crear una nueva plantilla de formularioy, a continuación, haga clic en
    Finalizar.

    El Asistente para proyectos de Microsoft Office, se crea un nuevo proyecto de Visual Studio .NET 2003 se denomina AttachmentEncoding. También se crea una plantilla de formulario de InfoPath. La plantilla de formulario de InfoPath se denomina AttachmentEncoding.

Crear una clase de codificador en Visual Studio .NET 2003

  1. En el Explorador de soluciones, haga clic en
    AttachmentEncoding, elija Agregary, a continuación, haga clic en Agregar nuevo elemento.
  2. En el cuadro de diálogo Agregar nuevo elemento , haga clic en
    Clase en el panel plantillas , escriba
    InfoPathAttachmentEncoder.cs en el
    Nombre de cuadro y, a continuación, haga clic en Abrir.
  3. Reemplace todo el código en el archivo InfoPathAttachmentEncoder.cs con el código siguiente.
    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());
    }
    }
    }

Crear una clase de descodificador en Visual Studio .NET 2003

  1. En el Explorador de soluciones, haga clic en
    AttachmentEncoding, elija Agregary, a continuación, haga clic en Agregar nuevo elemento.
  2. En el cuadro de diálogo Agregar nuevo elemento , haga clic en
    Clase en el panel plantillas , escriba
    InfoPathAttachmentDecoder.cs en el
    Nombre de cuadro y, a continuación, haga clic en Abrir.
  3. Reemplace todo el código en el archivo InfoPathAttachmentDecoder.cs con el código siguiente.
    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; }
    }
    }
    }


Agregue un control de archivo adjunto y un control de cuadro de texto al formulario de InfoPath

  1. En la plantilla de formulario AttachmentEncoding InfoPath, haga clic en los controles en el panel de tareas Tareas de diseño .
  2. En el panel de tareas controles , haga clic en el Archivo adjunto en
    Insertar controles.
  3. Haga clic en el control de Archivo adjunto y, a continuación, haga clic en Propiedades de archivo adjunto.
  4. En el cuadro de diálogo Propiedades de datos adjuntos de archivo , escriba theAttachmentField en el cuadro Nombre de campo y, a continuación, haga clic en Aceptar.
  5. En el panel de tareas controles , haga clic en Cuadro de texto en
    Insertar controles.
  6. Haga clic en el control de Cuadro de texto y, a continuación, haga clic en Propiedades de cuadro de texto.
  7. En el cuadro de diálogo Propiedades de cuadro de texto , escriba theAttachmentName en el cuadro Nombre de campo y, a continuación, haga clic en Aceptar.

Agregue un botón adjuntar al formulario de InfoPath

  1. En el panel de tareas controles , haga clic en el botón bajo
    Insertar controles.
  2. Haga clic en el nuevo control de botón y, a continuación, haga clic en Propiedades del botón.
  3. En el cuadro de diálogo Propiedades del botón , escriba
    Adjuntar en el cuadro etiqueta , escriba
    btnAttach en el cuadro ID y, a continuación, haga clic en
    Editar código del formulario.
  4. Agregue el código siguiente al método 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();
    }

Agregar un botón Guardar al formulario de InfoPath

  1. Cambie a la plantilla de formulario de AttachmentEncoding InfoPath.
  2. En el panel de tareas controles , haga clic en el botón bajo
    Insertar controles.
  3. Haga clic en el nuevo control de botón y, a continuación, haga clic en Propiedades del botón.
  4. En el cuadro de diálogo Propiedades del botón , escriba
    Guardar en el cuadro etiqueta , escriba
    btnSave en el cuadro ID y, a continuación, haga clic en
    Editar código del formulario.
  5. Agregue el código siguiente al método _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: En este código, reemplace < ruta de acceso para guardar el archivo > con la ubicación donde desea guardar el archivo.

Asegúrese de que la plantilla de formulario de InfoPath es plena confianza

Antes de probar este formulario, la plantilla de formulario de InfoPath debe ser de plena confianza. Puede utilizar uno de los métodos siguientes para asegurarse de que la plantilla de formulario de InfoPath es plena confianza:
  • Utilice la utilidad de configuración de Microsoft.NET Framework 1.1 para conceder permisos de plena confianza sólo para el código de Visual C#.
  • Utilice la herramienta RegForm desde el Kit de desarrollo de Software (SDK) de InfoPath para que el formulario en un formulario de plena confianza. Esto concede permisos de plena confianza en el código de Visual C#.
  • Utilizar un certificado de firma de código para firmar digitalmente el archivo de plantilla de formulario (.xsn). Cuando se utiliza un certificado de firma de código para firmar digitalmente el archivo de plantilla de formulario, se pide a los usuarios a confiar en el formulario cuando abran el formulario. Esto hace que el formulario de plena confianza. Por lo tanto, se conceden permisos de plena confianza en el código de Visual C#.
  • Utilice la macro IPFullTrust desde el SDK de InfoPath para que el formulario en un formulario de plena confianza. La macro IPFullTrust automatiza la configuración del archivo de manifiesto (.xsf) y el archivo de plantilla de formulario en el proyecto de InfoPath de plena confianza y, a continuación, la macro IPFullTrust registra automáticamente la plantilla de formulario.

    Para obtener más información acerca de cómo instalar y utilizar la macro, visite el siguiente sitio Web de Microsoft Developer Network (MSDN):
  • Utilizar automatización externo en InfoPath para llamar al método RegisterSolution . Normalmente, este método sólo se utiliza para el desarrollo de formularios porque sólo registra un formulario registrado para un equipo individual. Para cualquier formulario adicional, otros usuarios deben registrar los demás formularios en sus propios equipos. No se recomienda este método para formularios adicionales. Recomendamos cualquiera de los métodos anteriores al publicar el formulario.
Porque este formulario está en desarrollo de formulario, puede utilizar el último método. Para ello, busque la plantilla de formulario AttachmentEncoding InfoPath y, a continuación, siga estos pasos:
  1. En el menú Herramientas , haga clic en Opciones de formulario.
  2. Haga clic en la pestaña Seguridad .
  3. Haga clic para desactivar la casilla de verificación determinar automáticamente el nivel de seguridad según el diseño del formulario (recomendado) .

    Nota: InfoPath no puede detectar automáticamente la lógica empresarial que requiere permisos de plena confianza. Por lo tanto, debe conceder explícitamente permisos de plena confianza.
  4. Haga clic en Plena confianzay, a continuación, haga clic en
    OK.
  5. Cierre la plantilla de formulario de AttachmentEncoding InfoPath. Si se le pide guardar los cambios, haga clic en .

    Nota: No cierre el proyecto de Visual Studio .NET 2003.
  6. En Visual Studio .NET 2003, haga doble clic en el
    Archivo manifest.xsf en el Explorador de soluciones. Abre el archivo Manifest.xsf.
  7. En el nodo raíz, busque el atributo publishUrl . Quite el atributo publishUrl y el valor del atributo publishUrl .
  8. Guardar los cambios y, a continuación, cierre el archivo Manifest.xsf.
  9. Haga clic en Inicio, haga clic en Ejecutar, escriba notepady, a continuación, haga clic en
    OK.
  10. Agregue el código siguiente al archivo de texto en blanco.
    oApp = WScript.CreateObject("InfoPath.ExternalApplication");strAbsolutePath = "<project_folder_url>\\Manifest.xsf";
    oApp.RegisterSolution(strAbsolutePath,"overwrite");

    Nota: En este código, reemplace
    < project_folder_url > con la ruta de acceso del archivo Manifest.xsf de la carpeta del proyecto. Recuerde la ruta de acceso del archivo Manifest.xsf de escape. Todos los solo barras diagonales inversas (\) en la ruta de acceso deben reemplazarse con dos barras diagonales inversas (\).
  11. Guarde el archivo Manifest.xsf en el equipo como el archivo Register.js.
  12. Para llamar al método RegisterSolution , haga doble clic en el archivo Register.js que ha creado.

Probar el formulario

  1. En el proyecto AttachmentEncoding Visual Studio .NET 2003, haga clic en Inicio , en el menú Depurar . Esto inicia el formulario de InfoPath en modo de vista previa.
  2. En el formulario de InfoPath, escriba la ruta de acceso del archivo que desea adjuntar en el cuadro de texto y, a continuación, haga clic en
    Adjuntar.

    Nota: Haga doble clic en el control de Archivo adjunto para comprobar que el archivo está codificado correctamente.
  3. Haga clic en Guardar. Busque la ruta de acceso que proporciona en la sección "Agregar un botón Guardar al formulario de InfoPath".
  4. Para finalizar la prueba, haga clic en Cerrar vista previa.

Referencias

Para obtener más información sobre el formato de encabezado de datos adjuntos de archivo, visite el siguiente sitio Web de MSDN:
Propiedades

Id. de artículo: 892730 - Última revisión: 17 feb. 2017 - Revisión: 2

Microsoft Office InfoPath 2003

Comentarios