OneDrive/SharePoint 上のファイルが「Office で直接作成して保存」なのか「ローカルで作ってから同期(Sync)/手動アップロード」なのかを、Microsoft Graph API のメタデータだけで見分けたい——この要件に対して、判定の限界、現実的な推定手順、そして共有ファイルがどのドライブ(どのストレージ)に属するかを識別する方法まで、実務目線でまとめます。
結論:Microsoft Graph API だけで“作成経路”を100%断定できる単一プロパティはない
まず押さえるべきポイントは、Graph API の driveItem メタデータには「このファイルは Office でクラウド直保存された」「このファイルはローカル作成後に同期された」といった“経路そのもの”を確定できるフラグが用意されていないことです。
ただし、Graph が返してくれる複数のメタデータ(source / fileSystemInfo / createdBy など)を組み合わせることで、あくまで推定として「直保存っぽい」「同期っぽい」「判断不能」を分類する実装は可能です。推定が外れる代表パターンもあるため、最終的に監査証跡が必要なら Purview 監査ログ側へ寄せるのが現実解になります。
まずは用語をそろえる:Graph の “createdDateTime” が意味するもの
推定ロジックで混乱しやすいのが、Graph に出てくる “作成日時” が複数ある点です。特に重要なのが次の2つです。
| プロパティ | ざっくりした意味 | 直保存 vs アップロード推定への使い道 | 注意点 |
|---|---|---|---|
driveItem.createdDateTime | サービス(OneDrive/SharePoint)から見た作成時刻 | 基準(クラウド側の「作成扱い」時刻)になる | コピー/移動/復元などで“新規作成扱い”になると更新されることがある |
driveItem.fileSystemInfo.createdDateTime | クライアント(ローカル)ファイルシステムから報告された作成時刻 | ローカルで先に作られた痕跡になり得る | 「クライアントが提供する値」であり、常に期待通りとは限らない |
fileSystemInfo は「デバイスのローカルファイルシステムが報告する値」で、driveItem 側の時刻(サービス視点)とは性格が違います。ドキュメント上も、両者が異なる可能性が明示されており、「月曜に端末で作って火曜にアップロードしたなら、サービス上の作成は火曜、fileSystemInfo は月曜になり得る」例が示されています。
推定に使える“手がかり”一覧(Graph で見られるもの)
実務では、次の「複数の手がかり」を寄せ集めてスコアリングするのが扱いやすいです。
| 手がかり | 見る場所 | 強さ | 狙い | 主な落とし穴 |
|---|---|---|---|---|
| 作成元アプリの情報 | driveItem.source.application | 中 | Office/OneDrive/Teams など“由来”の推定 | 常に返るとは限らない/“直保存かどうか”までは断定できない |
| クラウド作成時刻 vs ローカル作成時刻 | createdDateTime と fileSystemInfo.createdDateTime | 中 | 「ローカルで先に作って後から上げた」痕跡の推定 | 同期やクライアントの実装で差が出ないことがある |
| 実行主体(ユーザー/アプリ/デバイス) | createdBy, lastModifiedBy(IdentitySet) | 弱〜中 | “どのクライアントっぽいか”の補助材料 | user しか出ないケースがある |
| 共有・別ドライブ参照か | remoteItem の有無 | 強 | 共有アイテム(別ドライブ所属)を見分ける | 検索結果などでも出る/ID が変わる注意あり |
手がかり:driveItem.source.application を見る
driveItem.source は、ファイルが作成された“ソースアプリ”のメタデータを持つ facet です。ここに application が入ると、Teams / OneDrive / SharePoint / PowerPoint / Office / Loop などの列挙値で返ってきます。
代表的な値(抜粋):
office:OfficepowerPoint:PowerPointoneDrive:OneDrivesharePoint:SharePointteams:Teamsloop:Loopother:サードパーティ
ここで勘違いしやすい点:source が Office だったからといって、それが「Office でクラウド直保存(Office for the web / 直保存)」を意味するとは限りません。“作成のきっかけ”が Office 系の体験だった、という程度の粒度で捉えると安全です。逆に source が取れない/unknown の場合もあるため、これ単体で判定しないのがコツです。
取得例(HTTP)
GET https://graph.microsoft.com/v1.0/drives/{driveId}/items/{itemId}?$select=id,name,createdDateTime,source,fileSystemInfo,createdBy,lastModifiedBy
レスポンス例(イメージ):
{
"id": "...",
"name": "sample.docx",
"createdDateTime": "2026-01-06T10:01:12Z",
"source": { "application": "office" },
"fileSystemInfo": { "createdDateTime": "2026-01-06T10:01:05Z" },
"createdBy": { "user": { "id": "...", "displayName": "..." } }
}
手がかり:createdDateTime と fileSystemInfo.createdDateTime を比較する
推定の基本は「クラウド側の作成時刻」と「ローカル側の作成時刻」の差分です。公式にも、fileSystemInfo はクライアントが提供する値で、driveItem 側(サービス視点)と異なる場合があると説明されています。
| 状況 | 典型的な関係 | 推定 | 実務での扱い |
|---|---|---|---|
| Office で作ってすぐ OneDrive に保存(直保存/ほぼ直) | 両者がほぼ同時刻(秒〜数十秒差) | 直保存の可能性が上がる | source/application など別の手がかりと合算して判断 |
| ローカルで作成 → 数分〜数日後にアップロード | fileSystemInfo.createdDateTime が明確に古い | ローカル起点の可能性が高い | 差分が大きいほどスコアを強くする |
| ローカル作成 → すぐ同期(自動) | 差分が小さい/同じに見える場合がある | 判定がぶれやすい | 「判断不能」扱いに落とす設計が安全 |
重要:公式は「クライアントが fileSystemInfo を書くべき」ことを示している一方で、実際の現場ではクライアント実装・同期タイミング・編集経路によって差が期待通りに出ないことがあります。したがって、差分だけで断定せず、閾値を決めた上で “推定スコア” に留めるのが堅牢です。
推定ルールの例(おすすめの現実解)
- 差分(createdDateTime – fileSystemInfo.createdDateTime)が30秒以内:直保存寄りに +1
- 差分が5分以上:ローカル起点(アップロード/同期)寄りに +2
- 差分が数時間〜数日:ローカル起点寄りに +3
fileSystemInfoが無い:このシグナルは使わない(0点)
切り分け検証(現場で差が出るか確認する手順)
推定ロジックを作る前に、自社テナントの実挙動を必ず検証するのが近道です(同期クライアントや OS 設定で挙動が変わるため)。
- OneDrive の同期対象外になりやすい場所(例:
C:\tempなど)で Office ファイルを新規作成 - 1〜2分待つ(“直後”だと時刻が寄りやすい)
- ブラウザの OneDrive/SharePoint から手動アップロード
- Graph で
createdDateTimeとfileSystemInfo.createdDateTimeを取得し差分を確認 - 同じ手順を「同期フォルダ内で新規作成」「Teams のファイルタブで作成」など複数パターンで比較
手がかり:createdBy / lastModifiedBy の application・device を探す
createdBy や lastModifiedBy は IdentitySet(Identity の集合)で、user / application / device などが入り得ます。
つまり、以下のような使い方ができます。
createdBy.applicationが入っている → “何かのアプリ経由” の可能性を加点lastModifiedBy.deviceが入っている → 端末編集の可能性を加点- どれも user のみ → シグナルが弱いので無理に判定しない
IdentitySet が取りうるキー(application/device/group/user)はドキュメントで定義されています。
取得例(HTTP)
GET https://graph.microsoft.com/v1.0/drives/{driveId}/items/{itemId}?$select=id,name,createdBy,lastModifiedBy
推定が崩れやすい“落とし穴”パターン
ここを押さえないと「たまに合うけど、たまに壊れる」実装になりがちです。次のケースは、直保存・同期・アップロードの境界が曖昧になりやすい代表例です。
- 同期フォルダ内で作成→即同期:ローカル作成とアップロードがほぼ同時刻になり、差分が出ない
- コピー/複製:作成時刻が“新規作成扱い”になり、由来推定が混ざる
- テンプレートから作成:内部的に一度ローカルで生成される挙動があり、時刻差が読みにくい
- 復元(ゴミ箱から戻す):時刻や履歴の扱いが通常作成と異なることがある
- 共有ファイルを「自分の OneDrive に追加」:remoteItem(別ドライブ参照)になり、そもそも“どのストレージ所属か”を先に整理する必要がある
おすすめ実装:推定スコアリング(“断定”ではなく“分類”にする)
実装で一番事故が少ないのは、「直保存/同期/アップロードを当てにいく」よりも、判定可能な範囲でスコア化し、閾値で分類する方式です。
| シグナル | 条件 | スコア例 | 狙い |
|---|---|---|---|
source.application | office / powerPoint | +2(直保存寄り) | Office 由来の可能性を上げる |
source.application | oneDrive / sharePoint | +1(クラウド操作寄り) | Web/OneDrive UI 由来の可能性 |
| 作成時刻差 | 差分 30秒以内 | +1(直保存寄り) | ほぼ同時なら直保存の可能性 |
| 作成時刻差 | 差分 5分以上 | +2(ローカル起点寄り) | 後追いアップロードの可能性 |
createdBy.application | 存在する | +1(補助) | アプリ経由の痕跡 |
remoteItem | 存在する | 別分類(共有) | まず所属ドライブ判定へ回す |
分類例:
- 直保存寄りスコアが高い → 「Office 直保存“っぽい”】【推定】
- ローカル起点寄りスコアが高い → 「同期/アップロード“っぽい”】【推定】
- スコアが拮抗/シグナル不足 → 「判断不能」
ポイント:「判断不能」ルートを用意することが、運用での炎上回避につながります。無理に二択にすると、例外ケースで必ず誤判定が出て監査・説明が難しくなります。
共有ファイルが「どの接続ストレージ(どのDrive/アカウント)」に属するかを識別する
共有アイテムの識別は、作成経路推定よりも“比較的堅い”です。鍵になるのは remoteItem です。
remoteItem は「driveItem が別の drive に存在するアイテムを参照している」ことを示し、共有・OneDrive に追加されたアイテム・検索結果などで返り得ると説明されています。
基本フロー
- 共有一覧を取得(例:
/me/drive/sharedWithMe) - レスポンスの
remoteItem.parentReference.driveIdを取得 GET /drives/{driveId}を呼び、ドライブ種別(personal/business/documentLibrary)と owner を確認
なお、/me/drive/sharedWithMe は非推奨(deprecated)で、一定期間は degraded state で動作し、その後データを返さなくなる旨が明記されています。運用設計では、この非推奨前提を必ず織り込んでください。
sharedWithMe の注意点(権限と非推奨)
sharedWithMeはアプリケーション権限がサポートされません(delegated 前提)。- 返ってくる driveItem は remoteItem facet を常に含む、とされています。
- 加えて、remoteItem の文脈では「remote item に移動された driveItem は id が変わる場合がある」という注意もあります。キャッシュ戦略は慎重に。
ドライブ種別の見分け方
drive リソースの driveType は、OneDrive personal は personal、OneDrive for Business は business、SharePoint のドキュメントライブラリは documentLibrary が返ると定義されています。
GET https://graph.microsoft.com/v1.0/drives/{driveId}?$select=id,driveType,owner
判定例:
driveType=documentLibrary→ SharePoint サイトのドキュメントライブラリ(Teams のファイルも多くはここ)driveType=business→ OneDrive for Business(個人の業務用 OneDrive)driveType=personal→ 個人向け OneDrive(Microsoft アカウント)
sharedWithMe が使えない/弱い環境の代替案:共有リンク起点で /shares を使う
共有一覧の取得が要件なら sharedWithMe が魅力的ですが、非推奨である以上、長期運用では代替ルートが必要になります。
共有リンク(sharing URL)や shareId を扱える運用なら、Graph の /shares API で共有アイテムにアクセスする方式があります。公式ドキュメントでも「shareId または sharing URL で shared item にアクセスする」ことが説明されています。
GET https://graph.microsoft.com/v1.0/shares/{shareIdOrEncodedSharingUrl}/driveItem
この方式は「共有リンクが手元にある」ことが前提になりますが、共有リンクを業務フロー内で保全できる(例:申請フォームに貼ってもらう/システム連携で保存する)なら、sharedWithMe の劣化影響を受けにくい設計に寄せられます。
“確実な証跡”が必要なら:Microsoft Purview の監査ログで確認する
コンプライアンス・インシデント対応など、「推定」ではなく「根拠(監査証跡)」が必要なケースでは、Graph メタデータではなく監査ログで追うのが正攻法です。
Purview の監査ログには、SharePoint/OneDrive の同期に関する操作として FileSyncUploadedFull(OneDrive 同期アプリによるアップロード)などが定義されています。
FileSyncUploadedFull:OneDrive 同期アプリ(OneDrive.exe)で、新規ファイルや変更をドキュメントライブラリ/OneDrive にアップロードFileSyncDownloadedFull:同期アプリでファイルを端末へダウンロード
監査ログ検索では、Operation 名(操作名)を正確に指定する必要があることも明記されています(誤字だと結果が返らない)。
Purview 監査ログでの実務的な見方
- 「最初に現れる操作が何か」を見る(同期系か、アップロード系か、共有/移動/コピーか)
- 同じファイル名でもコピーや移動で別物になり得るので、可能ならファイルの一意な識別子(サイト/ドライブ/アイテム)と突合する
- 監査ログ側の詳細プロパティ(エクスポート時の AuditData など)も合わせて確認する
また、監査ログ検索に必要なロール/権限(Audit Logs / View-Only Audit Logs など)や、検索の基本手順は Purview 側のガイダンスに沿って整備するとスムーズです。
運用で失敗しないための設計Tips
- 判定結果を“確定”として使わない:UI 表示や分析のラベル程度に留め、監査・規制対応の根拠にしない
- 「判断不能」を許容する:シグナル不足を無理に二択にしない(誤判定が最も高コスト)
- 要件が監査目的なら最初から Purview 前提で設計:Graph は補助、監査ログが本命
- sharedWithMe 依存を減らす:非推奨を前提に、共有リンク起点(/shares)や、業務フロー内での共有リンク保全を検討する
まとめ
Microsoft Graph API だけで「Office 直保存」か「ローカル作成→同期/アップロード」かを100%断定するのは難しく、現実的には source.application・時刻差(createdDateTime vs fileSystemInfo)・createdBy などを組み合わせた推定が限界です。一方で、共有ファイルの所属ドライブ特定は remoteItem と driveId を起点に比較的堅く実装できます。厳密な証跡が必要な要件では、Purview 監査ログ(同期操作の記録など)へ寄せるのが最短ルートです。

コメント