4
votes

I've recently added Flutter Web support for one of my projects which heavily uses Firebase services. Everything seems to work fine except Firebase Storage which doesn't work. I know that firebase_storage plugin currently doesn't work with Web so I tried instead with the regular firebase plugin but I can't get it to work.

I sometimes get different "red screen"-errors, but everything is related to pages which uses Firebase Storage. Here is one example of a red screen:

enter image description here

Here are the 3 files in which I previously used firebase_storage with success (Android) and with the code that I tried to get to work with th firebase plugin.

import 'package:firebase/firebase.dart' as fb;

// artiklar/images
final fb.StorageReference fbRefArtiklarImages =
    fb.app().storage().ref().child("artiklar").child("images");

// guider/categoryImages
final fb.StorageReference fbRefGuiderCategoryImages =
    fb.app().storage().ref().child("guider").child("categoryImages");
// guider/guideImages
final fb.StorageReference fbRefGuiderGuideImages =
    fb.app().storage().ref().child("guider").child("guideImages");

// kalender/images
final fb.StorageReference fbRefKalenderImages =
    fb.app().storage().ref().child("kalender").child("images");

// sidor/sidloggor
final fb.StorageReference fbRefSidorSidloggorImages =
    fb.app().storage().ref().child("sidor").child("sidloggor");
// sidor/sidcovers
final fb.StorageReference fbRefSidorSidcoversImages =
    fb.app().storage().ref().child("sidor").child("sidcovers");
// sidor/postImages/:sidaID/
final fb.StorageReference fbRefSidorPostImagesImages =
    fb.app().storage().ref().child("sidor").child("postImages");
// sidor/postImages/:sidaID/
final fb.StorageReference fbRefSidorKalenderImagesImages =
    fb.app().storage().ref().child("sidor").child("kalenderImages");

-

import 'dart:io';
import 'package:firebase/firebase.dart' as fb;

class StorageService {
  //STORAGE REFERENCES
  final fb.Storage _storage = fb.app().storage("gs://astoria-site.appspot.com");

  //UPLOADS IMAGE TO FIREBASE
  fb.UploadTask _uploadTask;

  Future<void> uploadStorageImage(File imageFile, String filePath) async {
    _uploadTask = _storage.ref().child(filePath).put(imageFile);
    return;
  }

  //DELETES IMAGE IN FIREBASE
  Future<void> deleteStorageImage(String filePath) async {
    try {
      await _storage.ref().child(filePath).delete();
    } catch (e) {
      print(e.toString());
    }

    return;
  }
}

-

import 'package:astoria/theme/colors.dart';
import 'package:cached_network_image/cached_network_image.dart';
import 'package:firebase/firebase.dart';
import 'package:flutter/material.dart';

class FirebaseStorageImage extends StatelessWidget {
  final String fileName;
  final StorageReference storageLocation;

  FirebaseStorageImage({
    @required this.fileName,
    @required this.storageLocation,
  });

  Future<String> _getImageURL() async {
    final StorageReference ref = storageLocation.child(fileName + ".jpg");

    try {
      var url = await ref.getDownloadURL();
      return url.toString();
    } catch (e) {
      return null;
    }
  }

  @override
  Widget build(BuildContext context) {
    return FutureBuilder(
      future: _getImageURL(),
      builder: (context, snapshot) {
        if (snapshot.connectionState == ConnectionState.done &&
            snapshot.hasData) {
          return Image(
            image: CachedNetworkImageProvider(snapshot.data),
            fit: BoxFit.cover,
          );
        } else if (snapshot.connectionState == ConnectionState.waiting) {
          //RETURN THIS WHILE WAITING FOR IMAGE
          return Container(color: lightGreyColor);
        } else {
          //RETURN THIS IF NO IMAGE WAS FOUND AT THAT LOCATION
          return Image(
            image: AssetImage("assets/images/placeholder.png"),
            fit: BoxFit.cover,
          );
        }
      },
    );
  }
}
2

2 Answers

2
votes

You need to pass a string to the ref method for it to work. For ease, change ref to refFromURL, then pass your bucket URL as a string to it as follows;

fb.app().storage().refFromURL("YOUR BUCKET URL HERE eg: 'gs://project-ID.appspot.com'")

Then you can safely add the remaining methods to it, such as; child() then put() or putString(). Goodluck!!!

0
votes

For those coming after me, here's a summary of achieving Firebase Storage image download for Flutter Web.

Thanks to Learn Flutter Code for this nice little tutorial.

Don't make Firebase Storage a dependency, just Firebase with:

import 'package:firebase/firebase.dart' as fb;

Then create a method:

        Future<Uri> myDownloadURL() async {return await fb.storage().refFromURL('gs://<your storage reference>').child('$id.jpg').getDownloadURL();}

Call it from a FutureBuilder like so:

        FutureBuilder<Uri>(
        future: myDownloadURL(),
        builder: (context, AsyncSnapshot<dynamic> snapshot) {
          if (snapshot.connectionState == ConnectionState.waiting) {
            return <Something as a placeholder>;
          }
          return CircleAvatar(
            radius: backgroundRadius * 2,
            child: Image.network(snapshot.data.toString()),
          );
        },
      )