はじめに
Flutterアプリケーションに画像やファイルの添付機能を追加するには、Firebase Storageを使用するのが便利です。Firebase Storageを利用することで、ユーザーがアップロードしたファイルをクラウドに安全に保存でき、さまざまなアプリケーションで共有できます。
この記事では、Firebase StorageをFlutterアプリに導入し、画像やファイルをアップロードする機能を実装する手順を解説します。エンジニア初心者にもわかりやすく、基本的なセットアップから具体的な実装までを説明します。
Firebase Storage のセットアップ
Firebase プロジェクトの作成
まずは、Firebaseにプロジェクトを作成して、FirebaseのStorageを有効にします。
Firebaseプロジェクトの作成・プロジェクトの初期化はこちらの記事で説明しています。
Firebase Authenticationのセットアップの手順後に続きを実施してください
(Firebase Authenticationを有効にする必要はありません)

- FirebaseのStorageサービスを有効化します。
- その後、FirestoreのStorageのモードを「テストモード」に設定します。これにより、初期開発段階で誰でもデータにアクセスできるようになります。
FlutterプロジェクトにFirebaseを追加
次に、FlutterプロジェクトにFirebaseを統合します。
pubspec.yaml
ファイルに必要なパッケージを追加します。
dependencies:
firebase_core: ^3.6.0
firebase_storage: ^12.3.3
image_picker: ^1.0.0
- パッケージをインストールします。
flutter pub get
main.dart
でFirebaseを初期化します。
import 'package:flutter/material.dart';
import 'package:firebase_core/firebase_core.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: StorageDemo(),
);
}
}
Firebase Storageへの画像アップロード
画像選択機能の実装
Flutterでは、image_pickerパッケージを使用して端末から画像を選択することができます。
まずは、端末から画像を選択する部分を実装します。
import 'dart:io';
import 'package:image_picker/image_picker.dart';
import 'package:flutter/material.dart';
class StorageDemo extends StatefulWidget {
@override
_StorageDemoState createState() => _StorageDemoState();
}
class _StorageDemoState extends State<StorageDemo> {
File? _image;
// 画像の選択
Future<void> _pickImage() async {
final pickedFile = await ImagePicker().pickImage(source: ImageSource.gallery);
if (pickedFile != null) {
setState(() {
_image = File(pickedFile.path);
});
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("Firebase Storage CRUD")),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
_image != null
? Image.file(_image!)
: Text("No image selected"),
SizedBox(height: 10),
ElevatedButton(
onPressed: _pickImage,
child: Text("Pick Image"),
),
],
),
),
);
}
}
端末に画像にアクセスするため、ios/Runner/Info.plist
に下記を追加います。
<key>NSCameraUsageDescription</key>
<string>We need access to the camera to take pictures</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>We need access to the photo library to select images</string>
このコードでは、ImagePicker
を使ってギャラリーから画像を選択し、その画像を表示しています。
Firebase Storage に画像をアップロード
次に、選択した画像をFirebase Storageにアップロードする機能を実装します。
下記コードでは、画像をuploads
フォルダにアップロードし、アップロード後に画像のダウンロードURLを取得します。
FirebaseStorage.instance.ref()
はFirebase Storageのルート参照を取得します。child('uploads/${_image!.path.split('/').last}')
は、アップロード先のパスを指定しています。この場合、uploads
フォルダの中に画像ファイルを保存します。${_image!.path.split('/').last}
で、画像ファイルのパスの最後の部分(つまりファイル名)を取得し、ファイル名を保持します。putFile()
メソッドを使用して、_image
として選択された画像ファイルを指定されたパスにアップロードします。
import 'package:firebase_storage/firebase_storage.dart';
// 画像のアップロード (Create)
Future<void> _uploadImage() async {
if (_image == null) return;
try {
final storageRef = FirebaseStorage.instance
.ref()
.child('uploads/${_image!.path.split('/').last}');
await storageRef.putFile(_image!);
final downloadUrl = await storageRef.getDownloadURL();
setState(() {
_downloadUrl = downloadUrl; // ダウンロードURLを保存して表示
});
print("Download URL: $downloadUrl");
} catch (e) {
print("Error uploading image: $e");
}
}
ファイルの削除
Firebase Storageにアップロードしたファイルを削除するには、delete
メソッドを使用します。
// ファイルの削除 (Delete)
Future<void> _deleteImage() async {
if (_downloadUrl == null) return;
try {
final storageRef = FirebaseStorage.instance.refFromURL(_downloadUrl!);
await storageRef.delete();
setState(() {
_image = null;
_downloadUrl = null;
});
print("Image deleted");
} catch (e) {
print("Error deleting image: $e");
}
}
アップロードしたファイル一覧を取得
アップロードしたファイルの一覧を取得するには、listAll
メソッドを使用します。
// アップロードされたファイルのリストを取得 (Read)
Future<void> _listUploadedFiles() async {
final ListResult result = await FirebaseStorage.instance.ref('uploads').listAll();
final List<String> urls = [];
for (var ref in result.items) {
final url = await ref.getDownloadURL();
urls.add(url);
}
setState(() {
_uploadedFiles = urls; // リストを更新
});
}
今回作成したサンプルコード
import 'dart:io';
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
import 'package:firebase_storage/firebase_storage.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: StorageDemo(),
);
}
}
class StorageDemo extends StatefulWidget {
@override
_StorageDemoState createState() => _StorageDemoState();
}
class _StorageDemoState extends State<StorageDemo> {
File? _image;
String? _downloadUrl;
List<String> _uploadedFiles = []; // アップロードされたファイルのリスト
// 画像の選択
Future<void> _pickImage() async {
final pickedFile = await ImagePicker().pickImage(source: ImageSource.gallery);
if (pickedFile != null) {
setState(() {
_image = File(pickedFile.path);
});
}
}
// 画像のアップロード (Create)
Future<void> _uploadImage() async {
if (_image == null) return;
try {
final storageRef = FirebaseStorage.instance
.ref()
.child('uploads/${_image!.path.split('/').last}');
await storageRef.putFile(_image!);
final downloadUrl = await storageRef.getDownloadURL();
setState(() {
_downloadUrl = downloadUrl; // ダウンロードURLを保存して表示
});
print("Download URL: $downloadUrl");
_listUploadedFiles(); // ファイル一覧を更新
} catch (e) {
print("Error uploading image: $e");
}
}
// アップロードされたファイルのリストを取得 (Read)
Future<void> _listUploadedFiles() async {
final ListResult result = await FirebaseStorage.instance.ref('uploads').listAll();
final List<String> urls = [];
for (var ref in result.items) {
final url = await ref.getDownloadURL();
urls.add(url);
}
setState(() {
_uploadedFiles = urls; // リストを更新
});
}
// ファイルの削除 (Delete)
Future<void> _deleteImage() async {
if (_downloadUrl == null) return;
try {
final storageRef = FirebaseStorage.instance.refFromURL(_downloadUrl!);
await storageRef.delete();
setState(() {
_image = null;
_downloadUrl = null;
});
print("Image deleted");
_listUploadedFiles(); // ファイル一覧を更新
} catch (e) {
print("Error deleting image: $e");
}
}
@override
void initState() {
super.initState();
_listUploadedFiles(); // 初期ロード時にファイル一覧を取得
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("Firebase Storage CRUD")),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
_image != null
? Image.file(_image!)
: Text("No image selected"),
SizedBox(height: 10),
ElevatedButton(
onPressed: _pickImage,
child: Text("Pick Image"),
),
ElevatedButton(
onPressed: _uploadImage,
child: Text("Upload Image"),
),
_downloadUrl != null
? Column(
children: [
Text("Download URL:"),
Text(_downloadUrl!),
ElevatedButton(
onPressed: _deleteImage,
child: Text("Delete Image"),
),
],
)
: Container(),
SizedBox(height: 20),
Expanded(
child: ListView.builder(
itemCount: _uploadedFiles.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(_uploadedFiles[index]),
onTap: () {
setState(() {
_downloadUrl = _uploadedFiles[index]; // 選択したファイルのURLをセット
});
},
);
},
),
),
],
),
),
);
}
}
まとめ
この記事では、FlutterアプリにFirebase Storageを導入して画像やファイルの添付機能を作成する方法を紹介しました。Firebase Storageを使うことで、画像やファイルをクラウドに保存し、ユーザー間で簡単に共有できるアプリを構築できます。
この記事のポイント
- Firebase StorageをFlutterアプリに導入する方法
- リアルタイムでの画像管理:アップロード、削除、画像の一覧取得が可能。
今後は、さらに高度な機能(ファイルのプレビューやダウンロードなど)も追加して、より使いやすいアプリにしていきましょう。
コメント