SharePointで同一DOCXを再アップロードするとSHA‑256ハッシュが毎回変わる原因と対策

SharePoint に同一の DOCX ファイルをアップロードし直しただけなのに、ダウンロードするとファイル サイズが数バイト変わり、SHA‑256 などのハッシュ値も毎回ズレる——監査や重複チェックをしていると、かなり気持ち悪い現象です。本記事では、この「customXml/itemProps が書き換えられる」問題の正体と、仕様・原因・無効化の可否・cTag の振る舞い・実務的な回避策までを、できるだけ具体的に整理します。

目次

SharePoint に同一 DOCX を再アップロードするとハッシュが変わる現象

まずは、現場で実際に観測されがちな現象を整理します。

項目内容
対象SharePoint ドキュメント ライブラリに保存された .docx(Word)ファイル
操作まったく同一のバイト列を持つ DOCX を、同じライブラリに再アップロードする 新規アップロードでも、既存ファイルへの上書きでも発生しうる
観測される現象ダウンロードした DOCX のサイズが、元ファイルと比べて 5〜6 バイト程度変化する SHA‑256 / SHA‑1 / MD5 など、バイト列ベースのハッシュ値が一致しない
差分比較の結果ZIP 展開して比較すると customXml/itemProps*.xml にのみ差分がある word/document.xml や docProps/core.xml / docProps/app.xml には差分がない

つまり、ユーザーから見ると「本文もプロパティも触っていないのに、SharePoint に置いた瞬間にバイト列が変わる」ように見えます。電子署名や独自の整合性チェックを行っているシステムでは、かなり重大な影響になりかねません。

DOCX の中で何が書き換えられているのか

DOCX ファイルは単なるバイナリではなく、「複数の XML ファイルなどを束ねた ZIP アーカイブ」です。代表的な構造は次のようになります。

sample.docx
 ├ [Content_Types].xml
 ├ _rels/
 ├ docProps/
 │   ├ core.xml
 │   └ app.xml
 ├ word/
 │   ├ document.xml
 │   ├ styles.xml
 │   └ ...
 └ customXml/
     ├ item1.xml
     ├ item2.xml
     ├ itemProps1.xml
     └ itemProps2.xml

今回問題になっているのは、その中の customXml/itemProps*.xml です。ここには、主に次のような情報が格納されます。

  • コンテンツ コントロール(リッチ テキスト、プレーン テキスト、ドロップダウンなど)のメタデータ
  • SharePoint 列やカスタム プロパティとのマッピング情報
  • 内部的な ID や状態管理に関する情報

差分ツールで比較すると、多くの場合、GUID のような値や内部 ID、属性の追加・削除など「人間には意味が分かりにくいが、Word と SharePoint の間で使われるメタデータ」が入れ替わっていることが分かります。

パーツ役割再アップロード時の変化
word/document.xml本文(段落・文字列・スタイルなど)変化しない
docProps/core.xmlタイトル・作成者・最終更新日時などのコア プロパティ原則変化しない(列からのデモーション時は変化しうる)
docProps/app.xmlページ数・文字数などアプリケーション情報変化しない
customXml/item*.xmlカスタム XML 部分(ビジネス データなど)内容によっては変化しうる
customXml/itemProps*.xmlカスタム XML・コンテンツ コントロールのメタ情報アップロードのたびに再生成され、バイト列が変化することがある

この itemProps*.xml を書き換えている張本人が、SharePoint の「プロパティ プロモーション / デモーション」機能です。

原因:プロパティ プロモーション / デモーション機能

SharePoint は、Office 文書を単なる「ファイル置き場」としてではなく、「メタデータ付きコンテンツ」として扱うために、アップロード時にドキュメントの中身を解析します。その際に動作するのが、次の 2 つの仕組みです。

  • プロパティ プロモーション(Property Promotion)
    DOCX 内のプロパティやコンテンツ コントロールを読み取り、ドキュメント ライブラリの列に値を「持ち上げる」。
  • プロパティ デモーション(Property Demotion)
    逆に、SharePoint 側の列の値を DOCX 内の該当プロパティに書き戻す。

この処理は、Word を開かなくても SharePoint 側で自動的に行われ、結果として DOCX パッケージ自体が書き換えられます。

タイミングSharePoint の動きDOCX への影響
アップロード直後Office ドキュメント パーサーがファイルを解析し、プロパティを抽出customXml/itemProps*.xml が再生成される
列(メタデータ)更新時必要に応じてプロパティ デモーションが走るコア プロパティや customXml 部分が更新されることがある
ユーザーが本文編集通常のチェックイン/保存処理本文だけでなく、コンテンツ コントロールに紐づく itemProps も変化しうる

ポイントは、「本文が変わっていなくても、SharePoint にアップロードした瞬間に DOCX の一部が書き換えられる」設計になっている、ということです。

よくある疑問への回答

これは SharePoint の仕様なのか?

結論から言うと、仕様どおりの動作です。

  • SharePoint は、Office 文書を解析し、ライブラリ列とドキュメント内プロパティの整合性を保つことを重視しています。
  • そのため、「ユーザーがアップロードしたオリジナルのバイト列を 1 ビットも変えない」ことは保証していません。
  • 特に customXml/itemProps*.xml のような内部的なメタデータについては、SharePoint/Office 側のバージョンやロジックによって生成される内容が変わる可能性があります。

監査や電子帳簿保存などの観点では納得しづらい部分ですが、「SharePoint に Office 文書を置く限り、プロパティ パーサーによる書き換えは起こりうる」という前提で設計する必要があります。

どの機能が書き換えを行っているのか?

書き換えを行っているのは、SharePoint の「Office 文書パーサー」と呼ばれるコンポーネントで、内部的にはプロパティ プロモーション / デモーション機能の一部として動作します。

概念的には、次のような処理フローになっています。

  1. ユーザーが DOCX をアップロードする。
  2. SharePoint がファイル拡張子やシグネチャから「Office Open XML 文書」と判定する。
  3. DOCX を ZIP として開き、docProps や customXml からプロパティを抽出する。
  4. ライブラリ列とのマッピングに従って、値を SharePoint 側のメタデータに反映する(プロモーション)。
  5. 逆方向のマッピングがある場合、列の値を DOCX に書き戻す(デモーション)。
  6. その際に customXml/itemProps*.xml が再生成される。

ユーザーからは見えませんが、アップロード後に走る非同期処理の一種と考えるとイメージしやすいと思います。

プロパティ プロモーションを無効化できるか?

SharePoint Online(Microsoft 365)の場合

SharePoint Online では、プロパティ プロモーション / デモーションを完全に無効化する設定は提供されていません。

  • テナント単位・サイト単位・ライブラリ単位いずれでも、「Office ドキュメント パーサーをオフにする」というスイッチはありません。
  • 一部のシナリオでは、特定の列やコンテンツ タイプを使わないことで影響を減らすことはできますが、itemProps*.xml の書き換えを完全に止めることはできません。

そのため、SharePoint Online を前提とした設計では、「バイト列は変わるもの」として、検証方法・ハッシュの取り方を工夫するのが現実的です。

オンプレミス(SharePoint Server)の場合

SharePoint Server(オンプレミス環境)では、サーバー全体の設定として Office ドキュメント パーサーを無効化するオプションが存在します。代表的なのが、管理シェルから設定する ParserEnabled プロパティです。

  • このプロパティを false にすると、アップロード時のプロパティ プロモーションが行われなくなります。
  • 結果として、DOCX のバイト列はアップロード前後で変化しにくくなります(ただし、他の要因で変わる可能性はゼロではない点に注意)。

ただし、この設定には大きな副作用があります。

  • ライブラリ列への自動プロパティ反映が行われなくなるため、メタデータ ベースの検索性が大きく低下します。
  • コンテンツ タイプやワークフローなど、プロパティ プロモーションを前提としている仕組みがある場合、期待どおりに動作しなくなることがあります。
  • ファーム全体設定であることが多く、一部サイトだけ無効化する、といった細かい制御は基本的に困難です。

そのため、「Integrity のために絶対にバイト列を変えたくない」という強い要件がある場合だけ慎重に検討すべきで、安易に有効・無効を切り替えるのはおすすめできません。

cTag が変わらないのは正しい動作か?

Microsoft Graph や OneDrive/SharePoint の API では、ファイルやアイテムに対して eTag / cTag といったタグが付与されています。

  • eTag:ファイルのバージョンを表すタグ。バイト列の変更と近いニュアンスだが、内部的な実装は公開されていない。
  • cTag:driveItem など「コンテンツ集合(コレクション)」の変更を表すタグ。ユーザーが認識できるコンテンツ変更にフォーカスしている。

問題のケースでは、customXml/itemProps*.xml のような「内部メタデータ」のみが変化しているため、Microsoft 側の判断として「ユーザーが認識できるコンテンツ変更ではない」扱いになり、cTag が更新されないことがあります。

  • 本文やユーザーが編集する列を変更した場合は、通常 cTag も更新されます。
  • 内部的な整合性調整やインデックス更新など、ユーザーからは見えない変更の場合は、cTag が変わらないこともあります。

したがって、「DOCX のバイト列が数バイト変わったのに cTag が変わらない」というのは、一見不思議に見えますが、仕様としておかしくはない動作だと考えられます。

バイト列を安定させる設定やガイダンスはあるか?

SharePoint 側の設定だけで「バイト列を完全に固定する」ことは困難です。そこで、アプリケーション側・運用側で工夫するパターンをまとめます。

アプローチ概要向いている用途
1. ハッシュ計算から customXml/itemProps* を除外するDOCX を ZIP として展開し、customXml/itemProps* を除外したうえで再 ZIP してハッシュを取る重複ファイル検知、改ざんチェック(customXml の変化を許容できる場合)
2. Office パーサーが触れない形式で保管するDOCX をそのままではなく ZIP や .bin に格納してアップロードし、ユーザー側で展開する電子帳簿保存・監査ログなど「バイト列完全一致」が最優先のシナリオ
3. PDF など別形式に変換して保存する編集を前提としない最終版は PDF に変換して保存し、Word 原本は内部システムで管理する稟議書・契約書・最終版の保管
4. バージョン管理を SharePoint メタデータに任せるハッシュ値ではなく、Modified 時刻や Version、Id を用いて同一性を判定する通常の業務文書管理、履歴管理

特に 1 と 2 が、この問題に対する現実的な対策になります。以下で少し詳しく見ていきます。

実装アイデア:customXml/itemProps を除外してハッシュを計算する

「本文やビジネス上の意味を持つ部分に変更がなければ同一ファイルとみなしたい」というケースでは、DOCX の中身を一度 ZIP として扱い、特定のパーツを除外してからハッシュを計算すると安定します。

基本的な考え方

  1. SharePoint から DOCX をダウンロードする。
  2. DOCX を ZIP として展開する。
  3. customXml/itemProps*.xml を削除、あるいは空ファイルで置き換える。
  4. 残りのファイルを、常に同じルール(ファイル順序・圧縮方法など)で再 ZIP する。
  5. その再 ZIP した結果に対して SHA‑256 を計算し、「論理的なコンテンツ ハッシュ」として利用する。

擬似コード形式で書くと次のようなイメージです(使用言語は問いません)。

1. input.docx を temp フォルダーに展開
2. temp/customXml/itemProps*.xml を削除
3. ファイル一覧をソート(例:パスの昇順)
4. 決め打ちの圧縮レベルで ZIP に固め直す
5. その ZIP に対して SHA-256 を計算

注意点として、ZIP は同じ中身でも「格納順序」や「タイムスタンプの扱い」によってバイト列が変わることがあります。ハッシュを安定させたい場合は、再 ZIP するときのルール(ソート順・圧縮レベル・タイムスタンプの固定など)を厳密に決めておくとよいでしょう。

メリットとデメリット

メリットデメリット
SharePoint の仕様変更に比較的強い ユーザーが見える本文やコア プロパティが変わらない限り、同じハッシュになる 既存の DOCX でも逐次適用できるアプリケーション側に ZIP 操作の実装が必要 「customXml/itemProps の差分も検出したい」場合には使えない 規制要件によっては「元ファイルそのもののハッシュ」でないと認められないケースもある

Office パーサーが触れない形式で保管するという割り切り

どうしても「アップロードしたバイト列に一切変更を加えたくない」場合、根本的な回避策として、Office 文書をそのまま置かないという選択肢があります。

ZIP / バイナリ ファイルとして保管する

例えば、次のような構成です。

  • ユーザーが編集する Word ファイル(example.docx)はアプリケーション内部で管理する。
  • SharePoint には example.docx をそのまま置くのではなく、暗号化や署名を施した上で example.bin としてアップロードする。
  • ユーザーがダウンロードするときは、アプリケーションが .bin を復号・展開して .docx として渡す。

拡張子が .docx でなければ、SharePoint はそれを「Office 文書」と認識せず、プロパティ パーサーも動作しません。このため、アップロード前後でバイト列が変わらず、ハッシュ値も安定します。

もちろん、「SharePoint 上で Word をそのまま開く」「共同編集する」といった利便性は犠牲になります。あくまで、電子署名や法的な証拠管理が最優先のケースで検討するアプローチです。

PDF への変換で最終版だけを SharePoint に置く

編集用の Word ファイルは別システムで管理し、SharePoint には「最終版 PDF」だけを置く、という割り切りもよく取られます。

  • Word ファイルは社内文書管理システムや Git などで管理。
  • 決裁後の最終版のみ PDF に変換して SharePoint に保存。
  • ユーザーには「SharePoint では閲覧専用」と割り切ってもらう。

PDF もメタデータを持ちますが、少なくとも DOCX の customXml/itemProps のように、コンテンツ コントロールと SharePoint 列の連携で書き換えられることはありません。編集性とのトレードオフではありますが、バイト列の安定性は高くなります。

バイト列ではなくメタデータを前提にした運用設計

ほとんどの業務システムでは、「毎回 SHA‑256 を比較するレベルの完全一致」が本当に必要なケースは多くありません。SharePoint の設計思想とも折り合いをつけつつ、現実的な運用に落とすための考え方を整理します。

用途別のおすすめ判定方法

用途おすすめ判定方法理由
単純な「変更されたかどうか」の確認Modified 日時、Version、Modified BySharePoint の標準機能でトラッキングされており、ユーザーにも分かりやすい
重複ファイルの検知customXml/itemProps 除外後の論理ハッシュ、またはファイル名+サイズ+コア プロパティの組み合わせ「ユーザーにとって同じ中身か」を重視できる
電子帳簿保存・監査など強い完全性要件SharePoint 以外のリポジトリに原本を保管し、SharePoint には派生物を保存SharePoint の自動書き換え仕様と折り合いをつけるため

Microsoft Graph / API 連携時のポイント

Graph API などからファイルを扱う場合も、返ってくるバイナリはすでに SharePoint 内部で書き換え済みである点に注意が必要です。

  • 初回アップロード直後に取得する場合と、後日取得する場合で、customXml 部分が変化していることがある。
  • API で独自ハッシュを保存する場合は、「いつのタイミングでハッシュを計算するか」を設計に明記しておくとよい。
  • file.hashes のようなプロパティ(SHA‑1 など)を利用する場合も、「SharePoint が保持している現在の状態のハッシュ」であることを理解しておく必要がある。

現象を自分で再現・検証する手順

実際に手元で現象を確かめたい場合の手順を、簡単に紹介します。

  1. 任意の Word 文書を作成し、sample.docx として保存する。
  2. Windows なら PowerShell や任意のツールで SHA‑256 を計算して控えておく。
  3. SharePoint ドキュメント ライブラリに sample.docx をアップロードする。
  4. そのファイルをダウンロードし、ファイル名を sample_from_sp1.docx として保存する。
  5. sample_from_sp1.docx の SHA‑256 を計算し、オリジナルと比較する。
  6. 同じオリジナル sample.docx をもう一度アップロード(または別のライブラリにアップロード)し、同様にダウンロードして sample_from_sp2.docx とする。
  7. 3 つのファイルの SHA‑256 とファイル サイズを比較する。
  8. 3 つのファイルをそれぞれ ZIP として展開し、customXml/itemProps*.xml だけを diff にかける。

多くの環境では、次のような結果になるはずです。

  • オリジナルと sample_from_sp1.docx のハッシュは一致しない。
  • sample_from_sp1.docx と sample_from_sp2.docx も、数バイトだけ異なりハッシュが一致しない。
  • ただし、word/document.xml など本文部分にはまったく差分がない。

この「本文は完全一致なのに、itemProps だけが微妙に違う」という事実が確認できれば、以降の設計議論もしやすくなるはずです。

よくある誤解と注意点

「SharePoint はアップロードしたファイルを一切書き換えない」という誤解

「ファイル サーバーの延長線上」として SharePoint を捉えていると、「アップロードしたバイナリには触らないはずだ」と考えがちです。しかし実際には、Office 文書についてはかなり積極的に解析・書き換えを行います。

  • プロパティ プロモーション / デモーション
  • IRM(情報保護)や DLP(データ漏えい防止)との連携
  • 検索インデックス、サムネイル生成など

これらの処理は、ユーザーの利便性やセキュリティ向上には有効ですが、「バイナリ完全一致」を期待すると齟齬が生じます。

「Graph API でダウンロードすればオリジナルのまま」という誤解

Graph や REST API を使っても、返ってくるのは「SharePoint に格納されている現在の状態のファイル」です。つまり、Web UI からダウンロードするのと本質的には同じであり、プロパティ パーサーによる書き換えを回避することはできません。

「API なら生バイナリが取れるはず」と思い込んでいると、ハッシュ値の検証で痛い目を見るので注意が必要です。

まとめ:SharePoint と DOCX ハッシュ値の付き合い方

最後に、本記事のポイントを整理します。

  • 同一バイト列の DOCX を SharePoint に再アップロードしても、customXml/itemProps*.xml が再生成されるため、ファイル サイズと SHA‑256 が毎回変わりうる。
  • これは SharePoint の プロパティ プロモーション / デモーション機能による仕様どおりの動作であり、本文(word/document.xml)やコア プロパティが変わっていなくても発生する。
  • SharePoint Online ではプロパティ プロモーションを完全に無効化するスイッチはなく、オンプレミスでも ParserEnabled をオフにするのは副作用が大きい。
  • cTag は「ユーザーから見えるコンテンツ変更」を基準にしており、customXml のような内部メタデータだけの変更では更新されないことがある。
  • 実務上は、次のような対策が現実的である。
    • ハッシュ計算時に customXml/itemProps* を除外し、「論理コンテンツ ハッシュ」を設計する。
    • どうしてもバイト列を変えたくない場合は、DOCX を ZIP や .bin に格納してアップロードするなど、Office パーサーが介入しない形式で保管する。
    • 通常の文書管理では、ハッシュ値ではなく Version / Modified / Id など SharePoint のメタデータに依拠する。

SharePoint は「Office 文書を積極的に理解して活用する」プラットフォームであり、その設計思想ゆえに DOCX のバイト列はどうしても揺らぎます。逆に言えば、その仕様を前提にしたうえで、「どこまでを同一とみなすか」「どの粒度で整合性を確認するか」をシステム側で定義してしまえば、ハッシュの揺らぎは単なる実装詳細に変わります。

これから SharePoint と Word を組み合わせたシステムを設計する際は、「バイト列の同一性」ではなく、「ユーザーにとって意味のあるコンテンツの同一性」を基準に、ハッシュやバージョン管理のルールを決めてみてください。

この記事を書いた人

実務の現場で詰まりがちなポイントを地図にするITブログ「IT trip」を運営。Windows/Office(Teams・Excel)からSQL、サーバ運用、ガジェットまで、再現性のある手順と“なぜそうなるか”を丁寧に解説します。読んだらすぐ試せること、そして迷った人の次の一歩が見えることを大切にしています。

コメント

コメントする

目次