Come codificare e decodificare un file allegato a livello di codice usando Visual C# in InfoPath 2010 o in InfoPath 2007

Riepilogo

In Microsoft InfoPath 2010 o in Microsoft Office InfoPath 2007 è possibile usare un controllo Allegato file per allegare un file al modello di modulo di InfoPath. In circostanze specifiche, è possibile codificare e quindi decodificare il file collegato al controllo Allegato file. In questo caso, è possibile usare Microsoft Visual C# per creare una classe Encoder e una decoderclass. È quindi possibile usare la classe Encoder e la classe Decoder per codificare e decodificare il file allegato. Questo articolo descrive come progettare un modello di modulo di InfoPath che codifica un file per l'allegato al modulo e decodifica l'allegato per il salvataggio nel file system.  

Per altre informazioni su come eseguire questa operazione in InfoPath 2003, fare clic sul numero dell'articolo della Microsoft Knowledge Base seguente:

892730 Come codificare e decodificare un file allegato a livello di codice usando Visual C# in InfoPath

Ulteriori informazioni

Microsoft fornisce esempi di programmazione solo a scopo illustrativo, senza alcuna garanzia espressa o implicita, comprese, senza limitazioni, le garanzie implicite di commerciabilità o idoneità per uno scopo particolare. In questo articolo si presuppone che l'utente conosca il linguaggio di programmazione in questione e gli strumenti utilizzati per creare ed eseguire il debug delle procedure. I tecnici Microsoft sono autorizzati a fornire spiegazioni in merito alla funzionalità di una particolare procedura, ma in nessun caso a modificare questi esempi per fornire funzionalità aggiuntive o a creare procedure atte a soddisfare specifiche esigenze.

Nell'esempio seguente verranno eseguiti i passaggi seguenti:

  1. Creare un modulo che include un progetto Visual C#.
  2. Creare una classe Encoder.
  3. Creare una classe Decoderclass.
  4. Modificare il modulo per chiamare il codice.
  5. Testare le operazioni di codice nel modulo .

Creare un modulo che include un progetto Visual C#

Creare un modello di modulo e un progetto usando le istruzioni per la versione di InfoPath in uso.

InfoPath 2010

  1. In InfoPath Designer creare un modello di modulo vuoto e quindi fare clic sull'icona Salva.
  2. Quando richiesto, digitare il nome del file e quindi fare clic su Salva.
  3. Fare clic sulla scheda **Sviluppatore **, quindi fare clic su Lingua.
  4. In Linguaggio del codice del modello di modulo selezionare C#, quindi fare clic su OK.

InfoPath 2007

  1. Nel menu **File **fare clic su Progetta un modello di modulo.
  2. Nel riquadro attività **Progettare un modello di modulo **fare clic su Vuoto e quindi fare clic su OK.
  3. Scegliere Salva dal menu File.
  4. Quando richiesto, digitare il nome file InfoPathAttachmentEncoding e quindi fare clic su Salva.
  5. Scegliere Opzioni modulo dal menu Strumenti.
  6. In Categoria nella finestra di dialogo **Opzioni modulo **fare clic su Programmazione.
  7. In Linguaggio di programmazione selezionare C# nell'elenco Linguaggio di codice del modello di modulo e quindi fare clic su OK.

Creare una classe Encoder

Creare una classe Encoder usando le istruzioni per la versione di InfoPath in uso.

InfoPath 2010

  1. Nella scheda Sviluppo fare clic su **Editor codice **per avviare l'editor Visual Studio Tools for Applications (VSTA).
  2. Nel menu Progetto fare clic su Aggiungi nuovo elemento.
  3. Fare clic per selezionare Classe.
  4. Nel campo Nome modificare il nome in InfoPathAttachmentEncoder.cs e quindi fare clic su Salva.
  5. Nella finestra del codice sostituire il codice esistente con il codice della sezione "Codice codificatore" seguente.

InfoPath 2007

  1. Avviare l'editor Visual Studio Tools for Applications (VSTA). 
  2. Nel riquadro **Esplora progetti **fare clic con il pulsante destro del mouse su InfoPathAttachmentEncoding, scegliere Aggiungi e quindi fare clic su Nuovo elemento.
  3. Nella sezione Modelli selezionare Classe, modificare il nome in InfoPathAttachmentEncoder.cs e quindi fare clic su Aggiungi.
  4. Nella finestra del codice incollare il codice della sezione "Codice codificatore" seguente.

Codice del codificatore

Usare il codice seguente in InfoPath 2010 o in 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());
}
}
}

Creare una classe Decoder

Creare una decoderclass usando le istruzioni per la versione di InfoPath in uso.

InfoPath 2010

  1. Nell'editor di codice scegliere Aggiungi nuovo elemento dal menu Progetto e quindi selezionare Classe.
  2. Nel campo Nome modificare il nome in InfoPathAttachmentDecoder.cs e quindi fare clic su Salva.
  3. Nella finestra del codice sostituire il codice esistente con il codice della sezione "Codice decodificatore" seguente. 

InfoPath 2007

  1. In VSTA, nel riquadro **Esplora progetti **, fare clic con il pulsante destro del mouse su InfoPathAttachmentEncoding, scegliere Aggiungi e quindi fare clic su Nuovo elemento.
  2. Nella sezione Modelli selezionare Classe, modificare il nome in InfoPathAttachmentDecoder.cs e quindi fare clic su Aggiungi.
  3. Nella finestra del codice incollare il codice dalla sezione "Codice decodificatore" seguente.

Codice decodificatore

Usare il codice seguente in InfoPath 2010 o in 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; }
}
}
}

Modificare il modulo

Aggiungere un controllo Allegato file, un controllo Casella di testo e un controllo Pulsante al modulo di InfoPath. A tal fine, attenersi alla seguente procedura:

  1. Aprire il riquadro attività Controlli usando le istruzioni per la versione di InfoPath in uso. 

    • InfoPath 2010: nel modello di modulo InfoPathAttachmentEncoding InfoPath, nella scheda **Home **, espandere la raccolta **Controls **.
    • InfoPath 2007: nel modello di modulo InfoPathAttachmentEncoding InfoPath fare clic su Controlli nel riquadro attività **Attività di progettazione**.
  2. Aggiungere un controllo File Attachment al modulo di InfoPath usando le istruzioni per la versione di InfoPath in uso:

    • InfoPath 2010: nel riquadro attività Controlli , in Oggetti, fare clic su File allegato.
    • InfoPath 2007: nel riquadro attività Controlli fare clic su File allegato in File e immagine.
  3. Fare clic con il pulsante destro del mouse sul controllo **File Allegato **, quindi scegliere Proprietà allegato file.

  4. Nella finestra di dialogo **Proprietà allegato file **digitare il campoAttachmentField nella casella **Nome campo **, quindi fare clic su OK.

  5. Aggiungere un controllo Casella di testo al modulo di InfoPath usando le istruzioni per la versione di InfoPath in uso:

    • InfoPath 2010: nel riquadro attività Controlli , in Input, fare clic su Casella di testo.
    • InfoPath 2007: nel riquadro attività Controlli , in Standard, fare clic su Casella di testo.
  6. Fare clic con il pulsante destro del mouse sul controllo Casella di testo e quindi scegliere Proprietà casella di testo.

  7. Nella finestra di dialogo **Proprietà casella di testo **digitare il ValoreAttachmentName nella casella **Nome campo **, quindi fare clic su OK.

  8. Aggiungere un pulsante Collega al modulo di InfoPath usando le istruzioni per la versione di InfoPath in uso:

    • InfoPath 2010: nel riquadro attività Controlli , in Oggetti, fare clic su Pulsante.
    • InfoPath 2007: nel riquadro attività Controlli , in Standard, fare clic su Pulsante.
  9. Fare clic con il pulsante destro del mouse sul nuovo controllo Button e quindi scegliere Proprietà pulsante.

  10. Nella finestra di dialogo **Proprietà pulsante **digitare Attach nella casella **Label **, digitare btnAttach nella casella ID e quindi fare clic su Modifica codice modulo.

  11. Passare alla parte superiore della finestra del codice e quindi aggiungere la riga di codice seguente:

    using InfoPathAttachmentEncoding;
    
  12. Tornare a "scrivere il codice qui" e quindi aggiungere il codice seguente:

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

Aggiungere un pulsante Salva al modulo di InfoPath

  1. Tornare al modello di modulo InfoPathAttachmentEncoding.

  2. Aggiungere un pulsante Salva usando le istruzioni per la versione di InfoPath in uso:

    • InfoPath 2010: nel riquadro attività Controlli , in Oggetti, fare clic su Pulsante.
    • InfoPath 2007: nel riquadro attività Controlli , in Standard, fare clic su Pulsante.
  3. Fare clic con il pulsante destro del mouse sul nuovo controllo Button e quindi scegliere Proprietà pulsante.

  4. Nella finestra di dialogo **Proprietà pulsante **digitare Salva nella casella **Etichetta **, digitare btnSave nella casella **ID **e quindi fare clic su Modifica codice modulo.

  5. Inserire il codice seguente:

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

Nota

In questo codice, il segnaposto Percorso della cartella per salvare l'allegato rappresenta il percorso in cui si vuole salvare il file.

Fare clic sull'icona Salva e quindi chiudere VSTA.

Testare il modulo

Prima che questo modulo possa allegare un file, il modello di modulo di InfoPath deve essere completamente attendibile. Per assicurarsi di questo, eseguire una delle azioni seguenti:

  • Usare un certificato di firma del codice per firmare digitalmente il file del modello di modulo (con estensione xsn). Quando si esegue questa operazione, agli utenti viene richiesto di considerare attendibile il modulo quando aprono il modulo. In questo modo il modulo è completamente attendibile. Di conseguenza, le autorizzazioni di attendibilità completa vengono concesse al codice Visual C#.
  • Creare un modello installabile.

Dopo aver verificato che il modello di modulo sia completamente attendibile, è necessario testarlo. A tal fine, attenersi alla seguente procedura:

  1. Aprire il modulo in modalità anteprima seguendo i passaggi per la versione di InfoPath in uso:

    • InfoPath 2010 Nella scheda Home fare clic su Anteprima.
    • InfoPath 2007 Nella barra degli strumenti Standard fare clic su Anteprima.
  2. Nel modulo di InfoPath digitare il percorso del file da allegare nella casella di testo e quindi fare clic su Allega.

    Nota Fare doppio clic sul controllo Allegato file per verificare che il file sia codificato correttamente. 

  3. Fare clic su Salva.

  4. Individuare il percorso specificato nel codice per la sezione "Aggiungi un pulsante Salva al modulo di InfoPath" e quindi assicurarsi che il file sia stato salvato in tale cartella. 

  5. Fare clic su Chiudi anteprima. Termina il test.