💡 Pełny działający przykład dostępny na GitHubie:
office-metadata-pii-cleanup-nodejs

Wprowadzenie

Punkt końcowy przesyłania przyjmuje plik DOCX od pracownika i zapisuje go w zgłoszeniu klienta. Tekst jest w porządku. Właściwości nie: plik zawiera nazwiska osoby, która go stworzyła, współpracownika, który go ostatnio zapisał, menedżera działu z szablonu korporacyjnego oraz, ponieważ pochodzi z SharePoint, zatwierdzającego, który go zatwierdził.

Sanitizer metadanych to mały skrypt, który usuwa te właściwości przed zapisaniem pliku, a następnie weryfikuje swoją pracę. Ten samouczek tworzy taki skrypt w Node.js przy użyciu GroupDocs.Metadata, w czterech krokach: wybieranie właściwości po tagu, wybieranie ich po nazwie, wyczyszczenie wszystkiego, gdy selektywność przestaje pomagać, oraz weryfikacja pozostałości. Każdy krok to kilka linii, a gotowy skrypt ma mniej niż sto.

Dlaczego czyszczenie metadanych ma znaczenie

Dane gromadzą się bez wyboru użytkownika. Word zapisuje Author i LastSavedBy z konta systemu operacyjnego przy każdym zapisie, prowadzi licznik wersji, śledzi TotalEditingTime i rejestruje LastPrinted. Serwery dokumentów dodają ścieżki przepływu pracy, identyfikatory zatwierdzających i URI typów treści przy zamykaniu. Żadne z tego nie pojawia się przy odczycie lub drukowaniu dokumentu, więc korekta nigdy tego nie wykryje.

Sens używania Node.js zamiast ręcznego usuwania polega na tym, że skrypt zwraca liczby: każde wywołanie usunięcia raportuje, ile właściwości zostało usuniętych, a tę liczbę można zapisać w logu, sprawdzić w teście lub dołączyć do rekordu, do którego dokument należy.

Istnieje drugi powód, mniej oczywisty, dopóki nie uruchomi się zadanie wsadowe. Ręczne czyszczenie to decyzja podjęta raz na plik przez osobę, która go obsługuje, więc dwie osoby czyszczące ten sam rodzaj dokumentu uzyskają różne wyniki. Skrypt ustala regułę w jednym miejscu: te same cztery tagi, te same listy podciągów, stosowane identycznie, niezależnie od tego, czy kolejka zawiera trzy pliki, czy trzy tysiące.

Wymagania wstępne

Pakiet jest Node.js poprzez Java, więc maszyna potrzebuje środowiska Java obok Node.

Instalacja

npm install @groupdocs/groupdocs.metadata

Przykładowy projekt blokuje wersję 26.7 i dodaje wpis overrides ustawiający nan na ^2.22.0, co utrzymuje budowanie natywnego powiązania na bieżących wydaniach Node. Bez pliku licencyjnego biblioteka działa w trybie ewaluacyjnym, co wystarczy, aby wykonać każdy krok tego samouczka.

Krok 1 – Wybieranie właściwości po ich znaczeniu

Nazwy właściwości różnią się w zależności od formatu i pakietu, więc pierwsza reguła dopasowuje się do tagów. ContainsTagSpecification przyjmuje tag i dopasowuje każdą właściwość, która go zawiera; .or() łączy specyfikacje w jedną.

const T = groupdocs.Tags;
const spec = new groupdocs.ContainsTagSpecification(T.getPerson().getCreator())
  .or(new groupdocs.ContainsTagSpecification(T.getPerson().getEditor()))
  .or(new groupdocs.ContainsTagSpecification(T.getPerson().getManager()))
  .or(new groupdocs.ContainsTagSpecification(T.getCorporate().getCompany()));
const affected = metadata.removeProperties(spec);
metadata.save(outputPath);

Kluczowe punkty:

  • Cztery tagi obejmują grupę tożsamości: twórca, edytor, menedżer oraz pole firmy korporacyjnej.
  • Tytuł, Temat i Słowa kluczowe pozostają nietknięte, więc indeks rekordów, który opiera się na nich, nadal działa.
  • removeProperties zwraca liczbę zmodyfikowanych elementów, a nie wartość logiczną.

Całość należy objąć try/finally z wywołaniem metadata.close() w bloku finally. Powiązanie trzyma plik otwarty do tego momentu, a pętla bez zamknięcia wyczerpuje uchwyty.

Krok 2 – Wybieranie właściwości po nazwie

Wątki komentarzy, liczniki wersji i pola serwera nie mają tagu. Dla nich WithNameSpecification(needle, false) dopasowuje każdą właściwość, której nazwa zawiera podany ciąg, a czteroliniowy konstruktor łączy po jednym podciągu:

let spec = null;
for (const needle of needles) {
  const s = new groupdocs.WithNameSpecification(needle, false /* fullMatch */);
  spec = spec ? spec.or(s) : s;
}
return spec;

Trzy przebiegi ponownie używają tego konstruktora z różnymi listami. Najpierw komentarze:

const affected = metadata.removeProperties(
  nameContainsSpec(['Comment', 'Reviewer', 'Reviewed']));
metadata.save(outputPath);

Linia edycji to grupa, którą najczęściej zapomina się usunąć, a jednocześnie opisuje, jak dokument został wyprodukowany:

const affected = metadata.removeProperties(nameContainsSpec([
  'Revision', 'TrackedChange', 'LastPrinted', 'TotalEditingTime', 'EditTime',
]));
metadata.save(outputPath);

Przebieg SharePoint to to samo wywołanie z Server, Workflow, Approver, ContentType i Template. Dopasowanie podciągów jest celowe: łapie CommentsCount razem z Comment bez konieczności utrzymywania dokładnej listy nazw dla każdego formatu.

Krok 3 – Wyczyszczenie wszystkiego, gdy selektywność przestaje pomagać

Dla kopii, która opuszcza organizację, jedno wywołanie zastępuje cztery poprzednie:

const affected = metadata.sanitize();
metadata.save(outputPath);

sanitize() usuwa wszystkie pakiety metadanych wykryte przez bibliotekę, w tym niestandardowe części OOXML, a jego liczba zazwyczaj przewyższa sumę liczb z poszczególnych przebiegów. Usuwa także Tytuł i Temat, dlatego powinien być używany na granicy, a nie w pętli przeglądowej.

Krok 4 – Weryfikacja, ponieważ ciche przeoczenie wygląda jak sukces

Skan ponownie używa tych samych specyfikacji poprzez findProperties, które odczytuje bez zapisu. Wynik jest kolekcją Java, więc przegląda się ją po indeksie:

const props = metadata.findProperties(tagSpec.or(nameSpec));
for (let i = 0; i < props.getCount(); i++) {
  const p = props.get_Item(i);
  const val = p.getValue && p.getValue();
  const value = val ? String(val.getRawValue ? val.getRawValue() : val) : '';
  if (!value || value === '0' || value === '0.0') continue;
  leaks.push(`${p.getName()}=${value}`);
}

Filtr pustych i zerowych wartości zasługuje na miejsce. Dodałem go po tym, jak jeden przebieg nie powiódł się z powodu licznika wersji, który został wyzerowany do 0, a skan wiernie zgłaszał go jako pozostawioną właściwość.

Kompletny działający przykład

Repozytorium łączy sześć funkcji w index.js, które stosuje licencję, uruchamia każdy przebieg na resources/pii-sample.docx, sprawdza, czy każdy plik wyjściowy istnieje, i kończy asercją, że lista wycieków jest pusta. Nieudana asercja kończy się kodem różnym od zera, więc całość działa jako kontrola w CI, a nie jako demonstracja do przeczytania.

Jedna rzecz warta skopiowania do własnej wersji: każdy przebieg odczytuje ten sam plik źródłowy i zapisuje osobny wynik, zamiast łańcuchowo przekazywać wyczyszczony plik do kolejnego kroku. Dzięki temu liczby zmodyfikowanych elementów są niezależne, więc linia logu dla przebiegu komentarzy raportuje to, co reguła komentarzy znalazła, a nie to, co pozostało po regule tożsamości.

Kiedy uruchomić ukierunkowany przebieg zamiast sanitize()?

Zawsze, gdy dokument jest jeszcze w użyciu. Pliki krążące między recenzentami polegają na Tytule, Temacie i Słowach kluczowych w wyszukiwaniu i klasyfikacji, a sanitize() usuwa wszystkie trzy wraz z danymi osobowymi. Uruchom przebiegi tożsamości i komentarzy podczas współpracy, zachowaj pola opisowe, a pełne wyczyszczenie zostaw na kopię, która faktycznie opuszcza organizację.

Zastosowania w rzeczywistym świecie

Obsługa przesyłania

Trasa Express sanitizuje załącznik przed zapisaniem go w magazynie, rejestruje liczbę zmodyfikowanych elementów w zgłoszeniu i odrzuca przesyłanie, gdy lista wycieków nie jest pusta.

Nocne zadanie eksportu

Worker przegląda folder eksportu, stosuje przebiegi tożsamości i serwera oraz przerywa zadanie zamiast logować ostrzeżenie, gdy dokument nadal zawiera resztkowe PII.

Brama przed publikacją

Krok budowania sanitizuje załączniki dokumentacji przed wydaniem, używając sanitize(), ponieważ żadne z tych plików nie wymaga zachowania metadanych.

Najlepsze praktyki i wskazówki

  • Zawsze zapisuj do nowej ścieżki, aby oryginał pozostał dostępny w razie sporu.
  • Zamykaj obiekt metadanych w bloku finally, szczególnie w pętlach.
  • Łącz specyfikacje przy pomocy .or() w zadaniach wsadowych; jedno otwarcie i jeden zapis przewyższają cztery.
  • Loguj liczbę zmodyfikowanych elementów dla każdego przebiegu, włączając zera, aby niewspierany format był widoczny.

Rozwiązywanie typowych problemów

Liczba zmodyfikowanych elementów wynosi zero w dokumencie, o którym wiesz, że jest brudny
Sprawdź, czy format wejściowy jest rozpoznawany, zanim uznasz plik za czysty; nieodczytany plik i czysty plik dają ten sam wynik zero.

Sprawdzenie wycieków zgłasza właściwości, które właśnie usunąłeś
Wskaż na zapisany plik wyjściowy, a nie na plik wejściowy. Skan odczytuje plik, który mu podasz.

Baloniki komentarzy wciąż są widoczne w Wordzie
Tekst komentarza znajduje się w treści dokumentu, nie w pakiecie metadanych. GroupDocs.Metadata usuwa właściwości związane z komentarzami; usunięcie samych baloników wymaga biblioteki edytującej treść, takiej jak Aspose.Words.

Zakończenie

Cztery kroki, sześć funkcji, jeden skrypt, który raportuje, co zrobił. Specyfikacje tagów obsługują grupę tożsamości we wszystkich formatach, specyfikacje nazw obejmują rodziny, które tagi nie klasyfikują, sanitize() obsługuje granicę, a skan wycieków zamienia całość w kontrolę. Sklonuj repozytorium, uruchom je na dokumencie, który przeszedł rzeczywistą rundę recenzji, i przyjrzyj się liczbom, zanim zdecydujesz, które przebiegi są potrzebne w Twoim potoku.

Dodatkowe zasoby