Upload di un file in una document library di WSS: ed i metadati?
Di per sè non è una cosa estremamente complicata. E’ possibile accedere ad una document library di Sharepoint come se fosse un normale path di rete. Detto questo, potete per esempio uploadare un file locale su un server con una banalissima File.Copy – pratica che a me personalmente non piace perchè non è asincrona e soprattutto blocca il thread corrente fino a quando l’operazione non è completata (con successo o meno).
Per l’upload ho preferito usare questo blocco di codice…
public void UploadDocument(string localFilename, string remoteFilename) { FileStream strm = new FileStream(localFilename, FileMode.Open, FileAccess.Read); BinaryReader reader = new BinaryReader(strm); byte[] fileContents = reader.ReadBytes((int)strm.Length); reader.Close(); strm.Close(); string sRemoteFileURL = Settings.Default.ServerWS + "/" + remoteFilename.Trim(); sRemoteFileURL.Replace(@" ", @"%20"); sRemoteFileURL.Replace(@"", @"/"); WebClient client = new WebClient(); client.Credentials = new NetworkCredential(this.Username, this.Password, this.Domain); client.UploadData(sRemoteFileURL, "PUT", fileContents); client.Dispose(); }
…che utilizza la classe WebClient per inviare uno stream di bytes sul server WSS. Il metodo UploadData – che io ho utilizzato – è comunque sincrono, ma ricordo che ci sono le varianti asincrone che seguono il pattern APM. Con questa tecnica, non dovete utilizzare alcun web-service, il che rende il tutto estremamente comodo e semplice da utilizzare.
La parte più complicata, se così vogliamo definirla, è aggiornare eventuali metadati previsti dalla document library nella quale abbiamo copiato il file. Per dirla breve, i metadati sono le colonne aggiuntive che noi abbiamo creato nella document library. Facciamo un piccolo esempio. Supponiamo di aver creato una document library sul nostro server WSS chiamata “Download”: lo scopo è quello di pubblicare su questa lista tutti i files che noi vogliamo far scaricare agli utenti. Oltre alle classiche informazioni di base (Nome del file, Dimensione, Ultima modifica) è possibile creare campi aggiuntivi, così da rendere più fruibile il contenuto della lista (Descrizione, Versione, Requisiti, Tipo di file, etc.). Come è possibile valorizzare questi metadati per un determinato file già uploadato sul server?
Qui le cose si fanno complicate, e bisogna necessariamente fare uso dei web-services di Sharepoint. Per questo tipo di operazione dobbiamo utilizzare il web-service con un url simile a questo:
http://nome_server_WSS/nome_document_library/_vti_bin/lists.asmx
Ecco il metodo che io ho scritto:
1 public void UpdateDocumentMetadata(string listName, string remoteFilename, Dictionary<string, string> values) 2 { 3 string finalFilePath = Settings.Default.ServerWS + "/" + remoteFilename; 4 this.ReadFileID(listName, remoteFilename); 5 string fileID = this.CacheFilesID[remoteFilename]; 6 7 #region Building command using XML 8 StringBuilder strBuilder = new StringBuilder(); 9 strBuilder.AppendLine("<Method ID='1' Cmd='Update'>"); 10 strBuilder.AppendFormat("<Field Name = 'ID'>{0}</Field>", fileID); 11 strBuilder.AppendFormat("<Field Name = 'FileRef'>{0}</Field>", finalFilePath); 12 13 Dictionary<string, string>.Enumerator enumerator = values.GetEnumerator(); 14 enumerator.MoveNext(); 15 16 do 17 { 18 strBuilder.AppendFormat("<Field Name = '{0}'>{1}</Field>", enumerator.Current.Key, enumerator.Current.Value); 19 } while (enumerator.MoveNext()); 20 21 strBuilder.AppendLine("</Method>"); 22 #endregion 23 24 XmlDocument doc = new XmlDocument(); 25 XmlElement elBatch = doc.CreateElement("Batch"); 26 elBatch.InnerXml = strBuilder.ToString(); 27 28 Lists l = new Lists(); 29 l.Credentials = new NetworkCredential(this.Username, this.Password, this.Domain); 30 l.UpdateListItems(listName, elBatch); 31 }
Al metodo arriva in input il nome della document library, il nome del file ed un Dictionary<string, string>. Quest’ultimo contiene coppie di key/value per i metadati che vogliamo aggiornare. Alla riga (3) ottengo il path completo del file sul server WSS (esempio: http://nome_server_wss/nome_document_library/nome_file). Alla riga (5) ottengo un ID univoco per il file: per farlo faccio uso di un altro metodo, ReadFileID, che trova il file e riempie una cache, in modo tale che se chiedo in un secondo momento l’ID dello stesso file uso la cache e non più il web-service che adesso voi vedete nascosto nel metodo ReadFileID().
Dalla riga (7) alla riga (26) costruisco un blocco XML che contiene un comando formattato da inviare all’engine di Sharepoint. L’XML contiene l’ID del file e contiene i metadati da aggiornare (ciclo do…while), formati da tanti <Field></Field>, dove l’attributo Name è il nome della colonna nella lista, ed il contenuto del tag è il valore che il metadato corrente deve assumere.
Dalla riga (28) alla riga (30) costruisco un’istanza del web-services ed eseguo una chiamata al metodo UpdateListItems(). Se tutto è andato a buon fine, potete navigare nella document library e controllare il file uploadato: esso avrà i metadati valorizzati così come abbiamo popolato il Dictionary!
Technorati Tags: SharePoint .NET Framework upload file