Flutter Web: Indexed DBをファイルストレージとして使う

インクルキャット JP
6 min readJun 18, 2021

--

モバイルからWebに移行する際の簡単なテクニック

サンプルアプリのイメージ

この記事は「Flutter Web: Use Indexed DB as File Storage」を翻訳したものです。

Flutterは、複数のプラットフォームにアプリを公開するための最も優れたソリューションの一つです。Flutter for mobileをFlutter for Webに移行する場合、通常はいくつかの変更を加えるだけで済みます。
しかし、Flutter for mobileでローカルファイルストレージを使用している場合、Web上でローカルファイルをどのように扱うかという、少し悩ましい問題があります。
私はその解決策の一つとして、Indexed DBを見つけました。ファイルストレージとしてどのように使っているかを説明します。

dart:ioはFlutter Webでサポートされていない

ローカルファイルを扱いたい場合は、Dart言語がデフォルトで提供しているdart:ioパッケージを使うのが一般的です。使い方は以下のようになります。

import 'dart:io'; final file = File(filePath); 
if (file.existsSync()) {
data = file.readAsBytesSync();
}

しかし、残念ながらFlutter Webでは、dart:ioパッケージを使うことができません。そのため、別の方法を探さなければなりません。

IndexedDBを使う

dart:ioの代替策として見つけたのがこれです。

IndexedDBは、ユーザーのブラウザ内にデータを永続的に保存するための方法です。 — MDN

IndexedDBは、大規模なNoSQLストレージシステムです。ユーザーのブラウザにあらゆるものを保存することができます。 — Google Developers

dart:ioのFileクラスと同じ機能を実現するために、Indexed DBを後ろに隠したクラスを考えました。こんな感じです。

final idbFile = IdbFile(filePath); 
if (await idbFile.exists()) {
data = await idbFile.readAsBytes();
}

上記のコードでは、dart:ioのFileクラスをオリジナルのIdbFileクラスに変更しただけです。また、同期的に動作する機能を実装するのは難しいと思われるので、awaitキーワードを追加しています。
どうですか?このようなクラスがあれば、通常のFileクラスと同じように使えると思いませんか?

idb_shim — インデックス付きDBを使用するためのDartパッケージ

idb_shimというDartパッケージを見つけました。Indexed DBを簡単に使えるようになるので便利です。公式サイトから使い方の例を紹介します。

// define the store name
const String storeName = "records";

// open the database
Database db = await idbFactory.open("my_records.db", version: 1,
onUpgradeNeeded: (VersionChangeEvent event) {
Database db = event.database;
// create the store
db.createObjectStore(storeName, autoIncrement: true);
});

// put some data
var txn = db.transaction(storeName, "readwrite");
var store = txn.objectStore(storeName);
var key = await store.put({"some": "data"});
await txn.completed;

// read some data
txn = db.transaction(storeName, "readonly");
store = txn.objectStore(storeName);
Map value = await store.getObject(key);
await txn.completed;

これと似たようなパッケージがいくつかあるので注意が必要です。ただし、それらのパッケージの中には、永続的なストレージではなく、メモリ上でのみ動作するものもあります。

データベース構造

ファイルストレージとして使用するために、Indexed DBのオブジェクトストア構造(名前は「files」)を以下のように考えました。(オブジェクト・ストアはテーブルのようなもので、プロパティはカラムのようなものです)

files オブジェクトストアの構造

非常にシンプルな構造になっていますね。実際に使うには他にもいろいろな属性があったほうがいいかもしれませんが、とりあえず使うにはこれで十分です。

このオブジェクトストアにデータを保存すると、Chromeデベロッパーツールで、このように実際のデータを確認することができます。

ソースコード

サンプルのソースコードはこちらから入手できます。

結論

私はすでに、この方法を使って、私のプライベートなFlutterアプリをモバイルからWebに移行しました。そして、このアプリがうまく動くことに満足しています。
約500KBのPDFファイルを使用していますが、ネイティブとWebのパフォーマンスに違いは感じられませんでした。

IdbFileクラスには、改善の余地がたくさんあります。例えば、ディレクトリ管理、ファイル検索などです。

このクラスを自分なりに改良して、この記事を参考にしていただければ、とても嬉しいです。

Free

Distraction-free reading. No ads.

Organize your knowledge with lists and highlights.

Tell your story. Find your audience.

Membership

Read member-only stories

Support writers you read most

Earn money for your writing

Listen to audio narrations

Read offline with the Medium app

--

--

インクルキャット JP
インクルキャット JP

Written by インクルキャット JP

情報格差の壁に挑む(挑みたい)個人アプリ開発者。

No responses yet

Write a response