FFFT

主にwebプロダクト開発に関連する話をつらつらと

ブラウザ側のデータ管理はWeb Storageで良いよねって思ってたけど容量問題にぶつかった

どんな背景からどんな問題が起きたか

あるアプリケーションの開発。
サーバサイドの都合で、一時保存APIが用意できない状況。
ただ、それなりに入力量が多いフォームでユーザーが途中まで入力しても離脱してまた再入力するケースを救いたい。

上記の状況を解決するべく、擬似的な一時保存機能の実現にWeb Storage(localStorage)を使おうとしたんですが...
容量問題にぶつかる。

単純なテキスト入力などのフォームの値であれば、奇想天外な量でない限り、全く問題なくlocalStorageの容量内に収まる。
しかし、今回のフォームは10MB以下の任意のファイルを最大6つアップロードできるようにする必要が。
アップロードされたファイルをbase64エンコードしてlocalStorageに入れたら容量不足に。(そりゃそうだ)

localStorageとのやりとりは王道のこちらのライブラリを使用。クロスブラウザで動作します。
github.com

こんなエラーが出ました。

Failed to execute 'setItem' on 'Storage': Setting the value of 'KEY_NAME' exceeded the quota.

そもそもWeb Storageとは

Web StorageHTML5から追加された仕組みで、ユーザーのブラウザにデータを管理(追加・上書き・取得・削除)させることができます。
localStorageとsessionStorageの2種類があり、違いはデータのライフサイクル(保存期間)。

・localStorageは永続(明示的にプログラムまたはブラウザのコンソールから消して初めて消える)
・sessionStorageはブラウザのタブが閉じられるまで

localStorageはサイトに何度訪れても最後に入力、または取得したデータを再現させたいシーンなどに利用されます。
ほとんどの場合、サーバサイドで永続化された情報を使えることが多い気がするので、
「このデータ、入力補助のためだけにしか使わないよね。サーバサイドで永続化させるの違うね。localStorage使うか。」みたいな場合に使っている気がする。後は本当は良くないけど、今回のように一時保存APIなどサーバサイドで用意するべきAPIがない場合など。

sessionStorageは主に入力内容を次の画面(確認画面とか)に引き継がせる役割で使われていることが多いです。
その名の通り、セッション単位で保持しておきたいデータを管理するのに最適という感じでしょうか。

どちらともオリジン単位でデータが管理されます。
key-value型のデータ保存形式でAPIもシンプル。
keyを指定してset, remove, getができ、stringで値が保存されます。

Web Storageにはどれだけデータを入れられるか

cookieとは比べ物にならないぐらい大容量だぜ!」っていうのは、よく聞いていたので何も考えずに作ってエラー出てから気づくという...
cookieが4KB(20個までなのでトータル80KB)だからたとえ比べ物にならなくても、今の時代のファイルじゃ容量越えるよねと。
Web Storageはデバイスのブラウザごとに容量の上限が変わるのですが、5MBを見ておけばメジャーなデバイスのブラウザでは動作するようです。
Androidだけ、やけに低く2MBちょっとらしい。Androidのブラウザも推奨ブラウザに含めるなら2MBを見ておくと良いかも。

どうしたか

諦めました。
具体的には、
・ファイルアップロード以外の入力情報をlocalStorageで管理し、擬似一時保存を実現させる
・ファイルはreactのcontextで管理し、ユーザーがリロードやタブ、ブラウザを閉じたらデータがなくなるのを許容する
にしました。

今回のアプリケーションの与件が「サーバサイドで一時保存APIを用意できない」だったので上記の対応にしましたが、本来的にはサーバサイドでAPIを用意する、ですね。