🦔

【Flutter】Firebase修行③ 『Storage』でファイルDL・UL✨

2023/02/24に公開

【修行】アプリにFirebaseを組み込む📱

この記事はFirebaseの修行のための忘備録的な感じで書いていきます✨
今回はデータ追加や削除の『Storage』をアプリに組み込んでいきます。
個人的に前回の『Firestore』とごっちゃになってます(ならんか笑)

👨『ええい、連邦のモビルスーツは化け物かぁ』

「Storage」の有効化手順

いつも大変お世話になっております下記サイトを確認して有効化していきます。

https://zenn.dev/kazutxt/books/flutter_practice_introduction/viewer/33_chapter4_storage

パッケージのインストール

今回は、firebase_storageのパッケージを利用します。詳細はパッケージの公式サイトを参照してください。
また、path_providerとimage_pickerも利用します。こちらはデバイスへの保存や画像の選択を行う際の補助的に利用するパッケージです。

https://pub.dev/packages/firebase_storage

https://pub.dev/packages/path_provider

https://pub.dev/packages/image_picker

pubspec.yaml
dependencies:
  flutter:
    sdk: flutter
  firebase_core: ^1.19.1
+ firebase_storage: ^8.0.5
+ path_provider: ^2.0.1
+ image_picker: ^0.7.4

あと下記に記載の実装例コード中には下の2つのパッケージも使用しております。
https://pub.dev/packages/loading_animation_widget
https://pub.dev/packages/animated_text_kit

実装例

このアプリでは、①Storageに登録している画像データのダウンロード②端末内の画像データをStorageへ保存するといった2つの動作を行います。

Twitterに上げた動画はこちら

実際のコードを下記に記載。

strage.dart
import 'dart:convert';
import 'dart:io';

import 'package:animated_text_kit/animated_text_kit.dart';
import 'package:firebase_storage/firebase_storage.dart';
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
import 'package:loading_animation_widget/loading_animation_widget.dart';
import 'package:path_provider/path_provider.dart';

class MyHomePage3 extends StatefulWidget {
  const MyHomePage3({Key? key, required this.title}) : super(key: key);

  final String title;

  @override
  _MyHomePageState3 createState() => _MyHomePageState3();
}

class _MyHomePageState3 extends State<MyHomePage3> {
  Image? _img;
  Text? _text;
  bool _readyDl = false;

  // ダウンロード処理
  Future<void> _download() async {
    // ファイルのダウンロード
    FirebaseStorage storage = FirebaseStorage.instance;
    Reference imageRef = storage.ref().child("DL").child("flutter.png");
    String imageUrl = await imageRef.getDownloadURL();
    Reference textRef = storage.ref("DL/hello.txt");
    var data = await textRef.getData();

    // 画面に反映
    setState(() {
      print(_readyDl);
      _img = Image.network(imageUrl);
      // _text = Text(ascii.decode(data!));
    });

    // ローカルにもファイルを書き込み
    Directory appDocDir = await getApplicationDocumentsDirectory();
    File downloadToFile = File("${appDocDir.path}/download-logo.png");
    try {
      await imageRef.writeToFile(downloadToFile);
    } catch (e) {
      print(e);
    }
  }

  // アップロード処理
  void _upload() async {
    // imagePickerで画像を選択する
    final pickerFile =
        await ImagePicker().pickImage(source: ImageSource.gallery);
    if (pickerFile == null) {
      return;
    }
    File file = File(pickerFile.path);
    FirebaseStorage storage = FirebaseStorage.instance;
    try {
      await storage.ref("UL/upload-pic.png").putFile(file);
      setState(() {
        _img = null;
        _text = const Text("UploadDone");
      });
    } catch (e) {
      print(e);
    }
  }

  @override
  void initState() {
    print(_readyDl);
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    const colorizeTextStyle = TextStyle(
      fontSize: 15.0,
      fontWeight: FontWeight.bold,
    );
    const colorizeColors = [
      Colors.pink,
      Colors.pinkAccent,
      Colors.yellow,
      Colors.pinkAccent,
      Colors.pink,
      // Colors.yellowAccent,
      // Colors.yellow,
      // Colors.orangeAccent,
    ];

    return Scaffold(
        appBar: AppBar(
          title: Text('Storage のテスト'),
          backgroundColor: Colors.grey,
        ),
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            // ダウンロードしたイメージとテキストを表示
            children: <Widget>[
              //変数_img がnull出ない場合(画像データが取得されている状態の場合)
              (_img != null)
                  ? Column(
                      children: [
                        Container(height: 350, width: 350, child: _img!),
                        SizedBox(
                          height: 10,
                        ),
                        Text(
                          'これでは道化だよ',
                          style: TextStyle(
                            fontSize: 30,
                          ),
                        )
                        // if (_text != null) _text!,
                      ],
                    )
                  : Center(
                      child: Column(children: <Widget>[
                        (_readyDl != false)
                            ? Column(
                                children: [
                                  LoadingAnimationWidget.fourRotatingDots(
                                    color: Colors.pinkAccent,
                                    size: 45,
                                  ),
                                  SizedBox(
                                    height: 10,
                                  ),
                                  AnimatedTextKit(
                                    repeatForever: true,
                                    animatedTexts: [
                                      ColorizeAnimatedText(
                                        ' Now DownLoading...',
                                        textStyle: colorizeTextStyle,
                                        colors: colorizeColors,
                                      ),
                                    ],
                                  ),
                                ],
                              )
                            : Container()
                      ]),
                    )
            ],
          ),
        ),
        floatingActionButton:
            Row(mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [
          FloatingActionButton(
            onPressed: () {
              setState(() {
                _readyDl = true;
              });
              _download();
              // Future.delayed(Duration(seconds: 5), () {
              //   _download();
              // });
            },
            child: const Icon(Icons.download_outlined),
            backgroundColor: Colors.indigoAccent,
          ),
          FloatingActionButton(
            onPressed: _upload,
            child: const Icon(Icons.upload_outlined),
            backgroundColor: Colors.pink,
          ),
        ]));
  }
}

動きとしてはこんな感じになります。

Discussion