FlutterでFirebase Storageから画像を落として表示するまで

Firebase CloudStorageと連携して、画像を落として表示するまでをまとめます。

## 準備
pubspec.yamlに必要なライブラリを記載します

```
firebase_storage: ^1.0.4
firebase_core: ^0.2.5+1
cached_network_image: ^0.5.1
```

これでflutter packages getをしてインストールしましょう

あと、firebaseのstorageで以下の設定をします

```
service firebase.storage {
  match /b/{bucket}/o {
    match /{allPaths=**} {
      allow read, write: if request.auth != null;
    }
  }
}
```
if request.auth != nullを削除します。後々これだとまずいですが、firebaseの認証も全てつけると面倒なので一旦アクセス可能にしておきます。

## firebaseの認証

最初にfirebaseとの接続を行う必要があります。これはfirebase_coreを使いましょう。
それぞれのキーを入れれば利用できます。自分の場合はこの辺知られると恐いので全て外部変数に持たせています。

```dart
import 'package:firebase_core/firebase_core.dart';
import 'dart:async';
import 'dart:io';
import '../.env.dart' as env;

Future<FirebaseApp> myFirebaseApp() {
  return FirebaseApp.configure(
    name: env.firebaseName,
    options: FirebaseOptions(
      googleAppID: Platform.isIOS ? env.iosGoogleAppID : env.androidGoogleAppID,
      gcmSenderID: env.gcmSenderID,
      apiKey: env.apiKey,
      projectID: env.projectID,
    ),
  );
}

```

main.dartでfirebaseとstorageインスタンスの呼び出しを行います。

```dart
import 'pages/top_page.dart';
import '.env.dart' as env;
import 'utils/firebase.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_storage/firebase_storage.dart';

void main() async {
  final FirebaseApp app = await myFirebaseApp();
  final FirebaseStorage storage =
      FirebaseStorage(app: app, storageBucket: env.storageBucket);
  runApp(MyApp(storage: storage));
}

class MyApp extends StatelessWidget {
  MyApp({this.storage});
  final FirebaseStorage storage;
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
          primarySwatch: Colors.blue,
          primaryColor: Colors.red,
          accentColor: Colors.yellowAccent),
      home: TopPage(storage: storage),
    );
  }
}

```

続いて画像の読み込み部分を書きます。URLを読み込んできて、cached_network_imageで画像を表示します。

```dart
import 'dart:async';
import 'package:cached_network_image/cached_network_image.dart';
import 'package:firebase_storage/firebase_storage.dart';
import 'package:flutter/material.dart';

class TopPage extends StatefulWidget {
  TopPage({this.storage});
  final FirebaseStorage storage;

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

class _TopPageState extends State<TopPage> {
  GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey();
  Image _image;

  Future<void> _downloadFile(String imgPath) async {
    // download path
    StorageReference ref = widget.storage.ref().child('images/$imgPath');
    final String url = await ref.getDownloadURL();
    final img = new Image(image: new CachedNetworkImageProvider(url));

    setState(() {
      _image = img;
    });

    final String name = await ref.getName();
    final String bucket = await ref.getBucket();
    final String path = await ref.getPath();
    print(
      'Success!\n Downloaded $name \n from url: $url @ bucket: $bucket\n '
          'at path: $path',
    );
  }

  @override
  Widget build(BuildContext context) {
    _downloadFile('1.jpeg');
    return Scaffold(
      key: _scaffoldKey,
      appBar: AppBar(
        title: const Text('Flutter Storage Example'),
      ),
      body: Center(
        child: Row(
          children: [
            _image,
          ],
        ),
      ),
    );
  }
}

```

## まとめ
クイックでしたが、flutterでfirebaseから画像をダウンロードする方法を書きました。
このあと、twitterみたいにスクロールしていったら逐次的にダウンロードしていく方法も考えたいと思います。