Tuesday, May 29, 2007

Sharepoint 2007: upload d'un document avec ses meta-data

J'ai dû récemment faire l'application suivante: Des documents étaient générés automatiquement par une application externe. Le but du programme était de récupérer ces documents pour les mettre dans une document list, avec leurs meta-data. Puis de lancer un workflow pour approbation avec différents paramètres. Dans cet article, je vais m'attacher à l'importation des fichiers dans la liste. Je ferai un autre article pour le workflow. Le premier réflexe est bien entendu de télécharger le document dans la liste puis de faire une correspondance entre les colonnes de la liste et des meta-data. Mais étant donné que je gère les versions dans cette liste, cette façon de faire risque d'incrémenter un numéro de version pour rien, suite à deux updates (un pour le document, un pour les meta-données) Mais en cherchant un peu, j'ai trouvé un overload bien pratique... La première chose est de considérer la liste comme un folder, et de récupérer dans ce folder la collection des fichiers existants. Le folder se récupère en utilisant le nom interne de la liste. Je spécifie bien le nom interne, c'est à dire le nom qui a été utilisé la première fois lors de la création de la liste (si elle a été créée via l'UI). On trouve ce nom en regardant dans l'url de la liste. Par exemple : http://dcmoss:50010/testgy/PurchaseOrder PurchaseOder est bien le nom du folder, même si la liste s'appelle "Purchase Order". SPFolder folder = _web.GetFolder("nom interne de la liste"); SPFileCollection files = folder.Files; Puis je récupère le fichier lui-même, en le stockant dans un stream mémoire FileStream fStream = File.OpenRead("fileName"); Pour terminer je crée l'URL du fichier, avec son nom: string url = "url Site web" + "nom interne de la liste" + "/" + Path.GetFileName("fileName"); Maintenant, les meta-data doivent être stockée dans une HashTable: HashTable MetaDataTable = new HashTable(); MetaDataTable.Add("nom de colonne", "valeur"); En réalité j'ai une classe qui parse le fichier texte et qui me renvoit une hashtable. Enfin, je l'ajoute le tout à la collection de fichier de la liste: SPFile currentFile = files.Add(url, fStream, MetaDataTable, true); Le flag True permet d'écraser un fichier s'il est déjà présent. En une ligne, on ajoute un fichier avec ses meta-données. Pas mal, non ? Voici un exemple de code pour uploader un document avec les meta-données: //Using required, especially System.IO; using System.Collections.Generic; using System.Collections; using System.Text; using Microsoft.SharePoint; using System.IO; namespace DocImport { public class DocManagement { //Some variables private string _DestUrlPath = string.Empty; private string _DestFolder = string.Empty; private SPSite _site = null; private SPWeb _web = null; public DocManagment(string DestUrl, string DestFolder) { _DestUrlPath = DestUrl; _DestFolder = DestFolder; _site = new SPSite(_DestUrlPath); _web = _site.OpenWeb(); } private bool _uploadDocument(string pdfFile, string txtFile) { try { //This is mandatory for avoiding an error _web.AllowUnsafeUpdates = true; //Use the list as a folder SPFolder folder = _web.GetFolder(_DestFolder); SPFileCollection files = folder.Files; //Get the file FileStream fStream = File.OpenRead(pdfFile); HashTable MetaDataTable = new HashTable(); MetaDataTable.Add("nom de colonne", "valeur"); //Set the destination url for SharePoint string url = _DestUrlPath + _DestFolder + "/" + Path.GetFileName(pdfFile); //Add document to the list with metadata, and overwrite an existing document with the same name SPFile currentFile = files.Add(url, fStream, MetaDataTable, true); fStream.Close(); return true; } catch (Exception x) { throw new Exception(x.Message); } } }

7 comments:

Lee Quan said...

Merci, c'est exactement ce que je cherche.
Une question concernant les noms des colonnes: Comment ajouter un "Titre" comme colonne ?
J'ai essayé "Title", mais ce marche pas !
Merci pour votre réponse.

Antoine Pichot said...

En fait, la colonne Title a un comportement particulier pour une DocLib : elle n'est pas disponible à la saisie pour les nouvelles entrées dans la liste (upload), mais si le document uploadé contient déjà une propriété Title (comme un document Word), alors cette colonne sera renseignée.
Pour remédier à cela, il est préférable de toujours passer par un Content Type, en supprimant (Remove) le champs Title et en créant un autre champs Title avec d'autres propriétés (ex: <Fields> <Field Type="Text" Name="Title" ShowInNewForm="TRUE" ShowInFileDlg="TRUE"
DisplayName="Title" Sealed="TRUE"></Field></Fields>
voir : http://gpeiris.blogspot.com/2006/05/display-title-field-when-uploading.html
Je vais écrire un article sur les Content Type bientôt.

Antoine Le Carpentier said...

Ce script est très interessant.
Justement je serai intéressé pour l'upload en masse de documents sur FS et de synchroniser les dates de dernières modification avec la colonne "Modifié le".
Des outils de migration le font, ce script permettrait-il de le faire avec le nom de la colonne SHP correspondant ?

ben said...

Bonjour,
Ce script est très intéressant, en effet.
Cependant connaissez vous un script d'upload de masse avec lecture des méta-data depuis un fichier xml.

Merci

Charles said...

Bonjour,

J'utilise la méthode myFolder.Files.Add(folderPath + "/" + _myFileInfo.Name, bArray, true); Le problème c'est que ça marche sur un site et pas pour un autre. Les 2 sites sont sur le même serveur et le compte qui lance l'.exe est admin du serveur et owner des sites WSS (v.2.0).

AllowUnsafeUpdates est sur true.

Merci de votre aide

Anonymous said...

Bonjour etant debutant dans sharepoint on me domande que pourvoir recuper les metadata d'un pdf et de les afficheou doit mettre le code que vous proposer
pouveez vous me donne une explication
D'avance merci

Antoine Pichot said...

J'ai mis le code dans une simple Console Application à démarrer en ligne de commande.