Back to Blog

There are a lot of tutorials on how to upload images to Firebase Cloud Storage. One constant theme that I have seen in these tutorials is the use of the “dart:html” package. Making use of this package will cause rendering issues when you run the app on mobile. So I decided to share a different way of uploading images that is safe on all platforms.

Background

In order to follow this tutorial, basic knowledge of Flutter and Dart is required. Knowledge of how to set up a Flutter project with Firebase, and enable web support.

Packages

For Image Upload we are going to make use of the following packages:

file_picker | Flutter PackageA package that allows you to use the native file explorer to pick single or multiple files, with extensions filtering… pub.dev

firebase_storage | Flutter PackageA Flutter plugin to use the Firebase Cloud Storage API. To learn more about Storage, please visit the Firebase website… pub.dev

universal_platform | Dart PackageCurrently, if you include the dart.io.Platform anywhere in your code, your will throw the following error on Web… pub.dev

image_picker | Flutter PackageA Flutter plugin for iOS and Android for picking images from the image library, and taking new pictures with the… pub.dev

Lets Code

All the code for this can be done in one file. Let’s create a file called “image_upload.dart”. Once that is done, import the following files:

1import 'package:flutter/material.dart';
2import 'package:file_picker/file_picker.dart';import 'package:firebase_storage/firebase_storage.dart' as firebase_storage;
3import 'package:universal_platform/universal_platform.dart';
4import 'package:image_picker/image_picker.dart';

Now that we have our imports in place, let’s create a void method called imgUpload make sure this method is an async method. This method can be called anything you like. Inside this method, we are going to do two things. 1) allow the user to choose an image to upload. 2) write our logic to upload the selected file. Here is the code you can copy and paste if you like or type it out:

1// create a file variable and a string variable
2File _image;
3String photoUrl;void imgUpload() async {
4    if (UniversalPlatform.isWeb) {
5      // initialize the file picker library
6      FilePickerResult result = await             FilePicker.platform.pickFiles();
7      // assign the result to a PlatformFile type
8      PlatformFile file = result.files.first;
9      // create our meta data information
10      final metadata = firebase_storage.SettableMetadata(
11        contentType: 'image/${file.extension}',
12      );
13      // path to where we want out file to be saved
14      firebase_storage.Reference ref = firebase_storage.FirebaseStorage.instance
15          .ref()
16          .child('pictures')
17          .child('/');
18      firebase_storage.UploadTask task;
19      task = ref.putData(file.bytes, metadata);
20    }
21    if (UniversalPlatform.isAndroid) {
22      // get image using image picker
23      final pickedFile =
24          await ImagePicker().getImage(source: ImageSource.gallery);
25      setState(() {
26        _image = File(pickedFile.path);
27      });
28      firebase_storage.Reference ref =
29          firebase_storage.FirebaseStorage.instance.ref().child("pictures/");firebase_storage.UploadTask task = ref.putFile(_image);
30      task.storage.ref().getDownloadURL().then((value) => {
31            photoUrl = value.toString(),
32          });
33    }
34  }

If you looked at the packages you might see that image_picker is compatible with the web, but we are not using it? Let me explain, you are right we can use it. But when the file is uploaded it will be uploaded as a stream, and since there is no way of figuring out the extension using image_picker, we make use of the FilePicker instead. If your wondering why the extension is not available here is a short summary. When we pick an image on the web using the image_picker library it is temporarily saved in the browser's local memory and hence when we try accessing it we will get something like “localhost:8080//random-string”.

Now if your thinking well file_picker is also compatible with mobile and still I choose imgage_picker? Well, I wanted to show how both can be used hence why I choose image_picker for mobile.

Our method is set up, now we need to call it. This will be done in our main method. We are going to create a GestureDetector widget and the child is going to be a Container. In this container, we are going to show the text choose image. We won’t update the content of the container once the image is uploaded, that will be a separate tutorial. Once again you can copy the code from below, or type it out:

1@override
2Widget build(BuildContext context) {
3  return SafeArea(
4    child: Scaffold(
5      body: GestureDetector(
6        onTap: () {
7          imgDetail();
8        },
9        child: Center(
10          child: Container(
11            height: 200,
12            width: 200,
13            decoration: BoxDecoration(
14              border: Border.all(
15                width: 2,
16              ),
17              borderRadius: BorderRadius.circular(10),
18            ),
19            child: Center(
20              child: Text("Choose Photo"),
21            ),
22          ),
23        ),
24      ),
25    ),
26  );
27}

Now that the code is set up, you can run it on any platform of choice and check your Firebase Storage tab and you will see the image uploaded there.

Here is the full gist:

Hoped you enjoyed this article and learned how to upload images to Cloud Storage using both mobile and web. Do leave a like and maybe even a follow so you see when the next article is published.