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 文書パーサー」と呼ばれるコンポーネントで、内部的にはプロパティ プロモーション / デモーション機能の一部として動作します。
概念的には、次のような処理フローになっています。
- ユーザーが DOCX をアップロードする。
- SharePoint がファイル拡張子やシグネチャから「Office Open XML 文書」と判定する。
- DOCX を ZIP として開き、
docPropsやcustomXmlからプロパティを抽出する。 - ライブラリ列とのマッピングに従って、値を SharePoint 側のメタデータに反映する(プロモーション)。
- 逆方向のマッピングがある場合、列の値を DOCX に書き戻す(デモーション)。
- その際に
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 として扱い、特定のパーツを除外してからハッシュを計算すると安定します。
基本的な考え方
- SharePoint から DOCX をダウンロードする。
- DOCX を ZIP として展開する。
customXml/itemProps*.xmlを削除、あるいは空ファイルで置き換える。- 残りのファイルを、常に同じルール(ファイル順序・圧縮方法など)で再 ZIP する。
- その再 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 By | SharePoint の標準機能でトラッキングされており、ユーザーにも分かりやすい |
| 重複ファイルの検知 | customXml/itemProps 除外後の論理ハッシュ、またはファイル名+サイズ+コア プロパティの組み合わせ | 「ユーザーにとって同じ中身か」を重視できる |
| 電子帳簿保存・監査など強い完全性要件 | SharePoint 以外のリポジトリに原本を保管し、SharePoint には派生物を保存 | SharePoint の自動書き換え仕様と折り合いをつけるため |
Microsoft Graph / API 連携時のポイント
Graph API などからファイルを扱う場合も、返ってくるバイナリはすでに SharePoint 内部で書き換え済みである点に注意が必要です。
- 初回アップロード直後に取得する場合と、後日取得する場合で、customXml 部分が変化していることがある。
- API で独自ハッシュを保存する場合は、「いつのタイミングでハッシュを計算するか」を設計に明記しておくとよい。
file.hashesのようなプロパティ(SHA‑1 など)を利用する場合も、「SharePoint が保持している現在の状態のハッシュ」であることを理解しておく必要がある。
現象を自分で再現・検証する手順
実際に手元で現象を確かめたい場合の手順を、簡単に紹介します。
- 任意の Word 文書を作成し、
sample.docxとして保存する。 - Windows なら PowerShell や任意のツールで SHA‑256 を計算して控えておく。
- SharePoint ドキュメント ライブラリに
sample.docxをアップロードする。 - そのファイルをダウンロードし、ファイル名を
sample_from_sp1.docxとして保存する。 sample_from_sp1.docxの SHA‑256 を計算し、オリジナルと比較する。- 同じオリジナル
sample.docxをもう一度アップロード(または別のライブラリにアップロード)し、同様にダウンロードしてsample_from_sp2.docxとする。 - 3 つのファイルの SHA‑256 とファイル サイズを比較する。
- 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 を組み合わせたシステムを設計する際は、「バイト列の同一性」ではなく、「ユーザーにとって意味のあるコンテンツの同一性」を基準に、ハッシュやバージョン管理のルールを決めてみてください。

コメント