Microsoft Graphの大容量アップロードが切れたら、最後に送信したbyte数だけを見て再開位置を決めません。Upload Sessionの状態を読み、サーバーが受け取っていない範囲と期限を確かめます。送信要求の応答を失った場合は、未実行か完了済みかを先に照合し、同じファイルの重複作成を避けます。
この記事はOneDrive・SharePointのdriveItem upload sessionを使う既存実装の診断を扱います。添付メールなど別のupload APIへそのまま適用しません。実ファイルの転送、session作成・照会、容量変更、削除は行っていません。数値例は計算の説明用で、製品での実測ではありません。
目次
元ファイルと宛先を固定する
sessionを再開する前に、sourceファイルが開始時と同じ内容・サイズであるかを確認します。途中で再生成されたファイルへ、以前の送信位置を流用してはいけません。pathが同じでも中身が変わる場合に備え、開始時のサイズやhashなど、実装に合う識別方法を残します。
表は横にスクロールできます
| 記録する対象 | 確認すること | 混ぜないもの |
|---|---|---|
| source | 内容・サイズ・版 | 同名の再生成ファイル |
| 宛先 | drive・親item・名前・更新対象 | 開発と本番の同名folder |
| session | uploadUrl・expirationDateTime | 別転送のsession |
| 転送状態 | サーバーの不足範囲・最後の応答 | clientが送信を試した量 |
| 作成条件 | fail/replace/rename等の方針 | 復旧時の無断上書き |
uploadUrlは事前認可されたURLなので、logやPRへ全文を貼りません。再開に必要な保管はaccess tokenと同様に閲覧範囲を限定します。再試行のたびにsessionを作り直しているなら、まず既存sessionの状態を追える設計か確認します。
sessionのGETで不足範囲を確認する
Microsoft公式createUploadSession資料(新しいタブで開く)は、接続が切れた転送ではuploadUrlへGETし、期限と不足byte範囲を取得して再開する手順を案内しています。clientの進捗表示が80%でも、サーバーが確定した範囲が同じとは限りません。
nextExpectedRangesは不足している範囲の情報であり、その文字列の大きさを次のchunkサイズへそのまま使う指示ではありません。すべての不足範囲が常に列挙されるとも限らないため、次に送れる位置と、実装側で守る分割条件を分けます。
GETが404なら、公式手順ではsessionが存在しないものとして全転送のやり直しが必要です。ただし最終要求の応答を失った直後なら、宛先に完成済みitemがあるかも、識別情報に基づいて確認します。存在しないsessionを再利用できないことと、完成済みのファイルがないことは別です。
byte範囲の計算と分割条件を揃える
Content-Lengthは今回送るbodyのbyte数、Content-Rangeはファイル全体の中の開始・終了・全長です。終了位置は含まれるため、長さはend minus start plus oneで計算します。文字数や圧縮前サイズを混ぜず、全要求で同じ全長を使います。
たとえば開始位置が327680、今回の長さも327680 byteなら、終了位置は655359です。これは範囲計算の架空例で、推奨chunkサイズや、そのまま実行する要求を示すものではありません。
公式資料では、各要求は60 MiB未満、分割する範囲は320 KiBの倍数、fragmentは順番に送る条件を案内しています。SDKを使う場合は大容量転送の公式SDK資料(新しいタブで開く)も確認し、そのSDKの分割・再開処理とアプリ独自処理を二重に動かさないようにします。端数となる最終fragmentの扱いも、採用するSDKやAPI手順に合わせます。
作成要求とuploadUrlへの転送を区別する
Graph側のsession作成には必要な認証が使われますが、取得したuploadUrlへのPUTへ同じAuthorizationを無条件に付ける実装にはしません。公式資料は、そのPUTにAuthorizationを付けると401になる可能性があると注意しています。HTTP clientの共通設定が、別hostのuploadUrlへbearerを付与していないかを確認します。
これを、すべてのGraph要求から認証を消す修正へ広げないでください。どの要求がsession作成で、どれが事前認可URLへの転送かを、request単位で分けます。uploadUrl自体をsecretとして扱う必要も残ります。
表は横にスクロールできます
| 応答や状態 | 次の処置 | 避けること |
|---|---|---|
| 転送途中の202 | 期限・次の範囲を確認 | ファイル完成と扱う |
| 416 | 状態を照会し重複範囲を確認 | 同じ範囲を無限再送 |
| 5xxや接続切断 | 状態照会と上限付きbackoff | 応答不明のまま最初から重複作成 |
| 期限切れ・session不存在 | 宛先状態を照合し新規転送を設計 | 古いURLを延々再利用 |
| 名前衝突や容量問題 | 原因とcommit状態を確認 | 無断rename・replace・課金変更 |
期限は固定値として記憶せず、最新の応答を保存します。sessionが生きていることと、必要な空き容量や宛先条件が満たされていることも別に確認します。
最後の202と、完成したdriveItemを分ける
通常のdeferCommitがfalseまたは未指定の経路では、最終範囲の転送で200または201とdriveItemが返ることが完了判断の手掛かりです。deferCommitがtrueなら明示的なcommitが必要で、OneDrive PersonalとBusiness・SharePointで方式が異なります。設定を確認せず、全byteを送った表示だけで完了にしません。
最終要求のtimeout後は、サーバー側で完成している可能性を残して宛先を照合します。名前だけでは同名の旧版かもしれないため、対象item ID、size、版や利用可能な検証情報を確認します。再開不能なら、承認済みの衝突方針に沿って新しい転送を行うか判断し、元の完成品を消してやり直す操作を標準にしません。
再開できることと、成果物が正しいことを確認する
許可された検証では、小さな素材やmock応答で、chunk途中の切断、応答喪失、session失効、既送範囲の再送、最終commitの分岐を確認します。実際のAPIへ障害負荷をかけずに確認できる部分と、転送実測が必要な部分を区別します。
完成後は宛先itemと元ファイルの対応、全長、必要なら内容の読取確認、重複itemの有無を確かめます。転送再開の成功だけで、書き込んだ中身まで保証したとしません。失敗時は元ファイルと診断記録を保全し、取り消しが必要なsession・作成済みitem・既存itemを分けて、許可された範囲だけを処置します。
