💡 Exemple complet fonctionnel disponible sur GitHub : scrub-office-document-pii-dotnet

L’ancienne méthode était pénible

La routine se déroule ainsi. Ouvrez le document, File, Info, Check for Issues, Inspect Document, cochez les cases, Remove All, enregistrez sous un nouveau nom, fermez, ouvrez le suivant. Quarante fichiers plus tard, quelqu’un remarque que l’inspection du document a également supprimé le titre sur lequel l’index des dossiers se base, et que la copie envoyée une heure plus tôt contenait encore l’ID d’approbateur SharePoint, parce que le fichier avait été enregistré depuis une autre application qui avait réécrit le champ.

La suppression des PII (informations personnelles identifiables) dans les métadonnées est une fonctionnalité de GroupDocs.Metadata pour .NET qui supprime de façon programmatique les propriétés contenant des informations d’identité des documents Office et rapporte ce qui reste ensuite. La routine manuelle échoue sur trois points : elle ne s’étend pas à plus d’une poignée de fichiers, elle fonctionne en tout ou rien quant aux champs à supprimer, et elle ne produit aucun enregistrement de ce qui a été retiré. Cet article montre la version .NET du même travail, groupe de propriétés à la fois.

Il est utile de savoir ce qui s’y trouve réellement. Un fichier Word qui a traversé une phase de révision comporte généralement Author et LastSavedBy provenant du compte Windows de la personne qui l’a enregistré, Manager et Company issus du modèle d’entreprise, un compteur de révisions, TotalEditingTime, un horodatage LastPrinted et des compteurs pour les fils de commentaires. Ajoutez SharePoint à la chaîne et vous obtenez également des identifiants d’approbateur, des chemins de workflow, des URI de type de contenu et le modèle à partir duquel le document a été créé. Aucun de ces éléments n’est visible sur la page, et tout voyage dans le même fichier.

Il existe une meilleure façon

Tout dans GroupDocs.Metadata pour .NET passe par un même moteur de recherche de propriétés. RemoveProperties prend une lambda sur MetadataProperty, supprime chaque propriété acceptée par la lambda et renvoie le nombre. FindProperties exécute la même lambda sans écrire. Les propriétés portent également des tags, ainsi Tags.Person.Creator identifie les champs de type auteur à travers les formats et les paquets au lieu de faire correspondre des noms littéraux qui diffèrent selon l’application productrice.

Cela offre trois formes de nettoyage au lieu d’un seul bouton : un passage par tag pour les champs d’identité, des passages par nom pour des familles comme les commentaires et les révisions, et Sanitize() lorsque rien ne doit survivre. Les trois renvoient des nombres, et ces nombres rendent le passage auditable.

La nouvelle méthode : un prédicat par groupe de propriétés

Étape 1 – Effacer les noms

Quatre vérifications de tags couvrent le groupe d’identité. Les champs descriptifs restent intacts, ce qui constitue la différence avec la fonction Tout supprimer de l’Inspecteur de documents :

using (var metadata = new Metadata(inputPath))
{
    if (metadata.FileFormat == FileFormat.Unknown) return 0;
    var affected = metadata.RemoveProperties(p =>
        p.Tags.Contains(Tags.Person.Creator) ||
        p.Tags.Contains(Tags.Person.Editor) ||
        p.Tags.Contains(Tags.Person.Manager) ||
        p.Tags.Contains(Tags.Corporate.Company));
    metadata.Save(outputPath);
    return affected;
}

La vérification FileFormat.Unknown est la garde qui maintient un zéro honnête : sans elle, un fichier illisible et un fichier propre apparaissent de la même façon pour l’appelant.

Étape 2 – Effacer les familles autour d’eux

Les commentaires, les révisions et les champs serveur n’ont pas de tag, donc le prédicat correspond aux noms à la place. La chronologie d’édition est le groupe le plus souvent oublié, et c’est celui qui indique comment un document a été produit :

using (var metadata = new Metadata(inputPath))
{
    if (metadata.FileFormat == FileFormat.Unknown) return 0;
    var affected = metadata.RemoveProperties(p =>
        p.Name != null && (
            p.Name.Contains("Revision") ||
            p.Name.Contains("TrackedChange") ||
            p.Name.Contains("LastPrinted") ||
            p.Name.Contains("TotalEditingTime") ||
            p.Name.Contains("EditTime")));
    metadata.Save(outputPath);
    return affected;
}

La correspondance par sous‑chaîne est intentionnelle : elle capture CommentsCount ainsi que Comment, et TotalEditingTime ainsi que EditTime, sans devoir maintenir une liste de noms exacts par format. Le passage SharePoint utilise le même appel avec Server, Workflow, Approver, ContentType et Template.

Étape 3 – Tout effacer, puis vérifier le résultat

À la frontière de confiance, un appel remplace les quatre passages :

using (var metadata = new Metadata(inputPath))
{
    if (metadata.FileFormat == FileFormat.Unknown) return 0;
    var affected = metadata.Sanitize();
    metadata.Save(outputPath);
    return affected;
}

Puis la partie pour laquelle la routine manuelle n’a aucun équivalent. L’analyse de vérification réutilise les prédicats de suppression via FindProperties et classe les survivants en deux listes :

foreach (var p in props)
{
    var value = p.InterpretedValue?.ToString() ?? p.Value?.ToString() ?? string.Empty;
    if (string.IsNullOrWhiteSpace(value)) continue;
    if (value == "0" || value == "0.0") continue;

    var entry = $"{p.Name}={value}";
    var name = p.Name ?? string.Empty;
    if (name.StartsWith("Comment") || name.StartsWith("Revision"))
        report.ContentLevelLeaks.Add(entry);
    else
        report.MetadataLeaks.Add(entry);
}

MetadataLeaks doit être vide avant qu’un fichier ne soit considéré comme nettoyé. ContentLevelLeaks est informatif : les commentaires Word et les auteurs des modifications suivies se trouvent dans word/document.xml, qui fait partie du contenu du corps, et les effacer nécessite une bibliothèque d’édition de contenu telle qu’Aspose.Words plutôt qu’une API de métadonnées.

Pourquoi ne pas simplement appeler Sanitize sur tout ?

Parce que la plupart des documents sont encore en cours d’utilisation. Sanitize() efface chaque paquet détecté, y compris Title, Subject et Keywords, les champs dont dépend un système d’archives et un index de recherche. Utilisez les passages ciblés tant qu’un fichier circule en interne, conservez les métadonnées descriptives actives, et réservez l’effacement complet à la copie qui quitte réellement l’organisation.

Comparaison côte à côte : avant vs. après

Inspection manuelle GroupDocs.Metadata pour .NET
Sélectivité Tout supprimer, champs descriptifs inclus un prédicat par groupe de propriétés
Couverture champs exposés par la boîte de dialogue tous les paquets détectés par la bibliothèque, parties OOXML personnalisées incluses
Enregistrement aucun nombre d’éléments affectés renvoyé par opération
Vérification réouvrir et examiner analyse FindProperties avec listes de métadonnées et de niveau de contenu
Lot de 200 fichiers 200 clics une boucle, cinq opérations, une ligne de journal par fichier

La ligne qui change le comportement est l’enregistrement. Dès que chaque passage renvoie un compte, la désinfection cesse d’être une étape que quelqu’un se souvient de faire et devient une donnée sur laquelle le pipeline peut s’appuyer : un seuil dans un test, un champ dans une table d’audit, une condition qui fait échouer un job nocturne. C’est également la ligne qu’une routine manuelle ne peut produire à aucun niveau de discipline.

Exemple réel : le hook avant envoi

Un portail d’assistance permet au personnel de joindre des documents aux tickets clients. Le gestionnaire de pièces jointes exécute désormais le passage d’identité et le passage serveur avant que le fichier ne soit stocké, enregistre les deux comptes dans le ticket, et effectue la vérification des fuites sur la copie enregistrée. Une liste de fuites de métadonnées non vide rejette le téléchargement avec un message indiquant la propriété incriminée, de sorte que la personne qui joint le fichier le découvre immédiatement plutôt qu’après qu’il ait atteint le client.

Deux détails rendent ce hook pratique. Les passages écrivent vers un nouveau chemin, de sorte que l’original reste dans le stockage personnel du membre du personnel et rien n’est détruit par une étape automatisée. Et les comptes sont enregistrés dans le ticket à côté de la pièce jointe, ce qui signifie que la réponse à « ce qui a été retiré de ce document » est un nombre stocké plutôt qu’une supposition sur ce que le pipeline fait habituellement.

La première fois que j’ai appliqué cette vérification à un vrai modèle, il est revenu avec une valeur Manager que le passage d’identité avait supprimée quelques secondes auparavant et que le modèle d’entreprise avait réécrite immédiatement lors de l’enregistrement. L’appel de suppression fonctionnait exactement comme documenté ; le pipeline autour était le problème, et seul le re‑lecture l’a révélé.

Que pouvez‑vous faire d’autre avec GroupDocs.Metadata ?

Le même moteur de prédicats lit. Comparer les propriétés entre deux versions d’un document fait apparaître les changements de propriété et les ré‑authorisations en dehors du processus de révision, et la vue d’ensemble du nettoyage des métadonnées explique où un outil interactif s’intègre encore à côté d’un passage piloté par API. Comme le système de tags couvre plusieurs formats, le prédicat d’identité écrit ici fonctionne également sur les PDF, les images et les fichiers audio sans modification.

Cette portabilité mérite d’être prise en compte. Une règle de nettoyage écrite comme une lambda sur MetadataProperty est du C# ordinaire, elle peut donc résider dans une bibliothèque partagée, être testée unitairement sur des documents de référence, et être appliquée par le service qui en a besoin : un point de terminaison d’exportation, un job planifié d’archives, ou une étape de build qui nettoie les pièces jointes de documentation avant la publication. Les règles restent au même endroit ; seuls les points d’appel changent.

Conclusion

Quatre passages ciblés, un nettoyage complet, une analyse de vérification. Cet ensemble couvre la gamme pratique pour les documents Office : conserver les métadonnées descriptives pendant la circulation d’un fichier, tout effacer lorsqu’il quitte l’organisation, et prouver le résultat dans les deux cas. Clonez l’exemple, exécutez‑le sur un document qui a traversé une vraie phase de révision, et lisez les nombres d’éléments affectés. Ils sont généralement plus élevés que prévu, ce qui est tout l’enjeu.

Ressources supplémentaires