Bird
Raised Fist0
Fluttermobile~20 mins

Cloud Storage for files in Flutter - Mini App: Build & Ship

Choose your learning style10 modes available
Build: File Upload Screen
This screen lets users pick an image file from their device and upload it to cloud storage. It shows upload progress and displays the uploaded image after success.
Target UI
-------------------------
| File Upload Screen     |
|-----------------------|
| [Choose Image]         |
|                       |
| Upload Progress: 0%    |
|                       |
| [Upload Image]         |
|                       |
| Uploaded Image Preview |
| [No image selected]    |
-------------------------
A button to pick an image file from the device gallery
Show the selected image preview before upload
An upload button to send the image to Firebase Cloud Storage
Display upload progress percentage while uploading
After upload, show the uploaded image from cloud storage URL
Starter Code
Flutter
import 'package:flutter/material.dart';

class FileUploadScreen extends StatefulWidget {
  @override
  State<FileUploadScreen> createState() => _FileUploadScreenState();
}

class _FileUploadScreenState extends State<FileUploadScreen> {
  // TODO: Add variables for image file, upload progress, and download URL

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('File Upload Screen')),
      body: Padding(
        padding: const EdgeInsets.all(16),
        child: Column(
          children: [
            ElevatedButton(
              onPressed: () {
                // TODO: Implement image picker
              },
              child: const Text('Choose Image'),
            ),
            const SizedBox(height: 20),
            // TODO: Show selected image preview or placeholder
            const SizedBox(height: 20),
            ElevatedButton(
              onPressed: () {
                // TODO: Implement upload to cloud storage
              },
              child: const Text('Upload Image'),
            ),
            const SizedBox(height: 20),
            // TODO: Show upload progress
            const SizedBox(height: 20),
            // TODO: Show uploaded image from cloud URL
          ],
        ),
      ),
    );
  }
}
Task 1
Task 2
Task 3
Task 4
Task 5
Solution
Flutter
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
import 'package:firebase_storage/firebase_storage.dart';

class FileUploadScreen extends StatefulWidget {
  @override
  State<FileUploadScreen> createState() => _FileUploadScreenState();
}

class _FileUploadScreenState extends State<FileUploadScreen> {
  File? _imageFile;
  double _uploadProgress = 0.0;
  String? _downloadUrl;

  final ImagePicker _picker = ImagePicker();

  Future<void> _pickImage() async {
    final XFile? pickedFile = await _picker.pickImage(source: ImageSource.gallery);
    if (pickedFile != null) {
      setState(() {
        _imageFile = File(pickedFile.path);
        _downloadUrl = null;
        _uploadProgress = 0.0;
      });
    }
  }

  Future<void> _uploadImage() async {
    if (_imageFile == null) return;
    final fileName = DateTime.now().millisecondsSinceEpoch.toString();
    final ref = FirebaseStorage.instance.ref().child('uploads/$fileName.jpg');
    final uploadTask = ref.putFile(_imageFile!);

    uploadTask.snapshotEvents.listen((TaskSnapshot snapshot) {
      setState(() {
        _uploadProgress = snapshot.bytesTransferred / snapshot.totalBytes;
      });
    });

    try {
      await uploadTask;
      final url = await ref.getDownloadURL();
      setState(() {
        _downloadUrl = url;
      });
    } catch (e) {
      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(content: Text('Upload failed: $e')),
      );
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('File Upload Screen')),
      body: Padding(
        padding: const EdgeInsets.all(16),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.center,
          children: [
            ElevatedButton(
              onPressed: _pickImage,
              child: const Text('Choose Image'),
            ),
            const SizedBox(height: 20),
            _imageFile != null
                ? Image.file(_imageFile!, height: 150)
                : const Text('No image selected'),
            const SizedBox(height: 20),
            ElevatedButton(
              onPressed: _uploadImage,
              child: const Text('Upload Image'),
            ),
            const SizedBox(height: 20),
            Text('Upload Progress: ${(_uploadProgress * 100).toStringAsFixed(0)}%'),
            const SizedBox(height: 20),
            _downloadUrl != null
                ? Image.network(_downloadUrl!, height: 150)
                : const SizedBox.shrink(),
          ],
        ),
      ),
    );
  }
}

This solution uses the image_picker package to let the user select an image from their gallery. The selected image file is stored in a File variable and shown as a preview.

When the user taps the upload button, the app uploads the image file to Firebase Cloud Storage under a unique filename based on the current timestamp.

The upload progress is tracked by listening to snapshotEvents from the upload task, and the UI updates the progress percentage accordingly.

After the upload completes, the app fetches the download URL from Firebase Storage and displays the uploaded image from the cloud.

This approach gives a clear, simple UI for picking, uploading, and viewing images stored in the cloud.

Final Result
Completed Screen
-------------------------
| File Upload Screen     |
|-----------------------|
| [Choose Image]         |
|                       |
| (Image preview here)   |
|                       |
| [Upload Image]         |
|                       |
| Upload Progress: 75%   |
|                       |
| (Uploaded image here)  |
-------------------------
Tap 'Choose Image' opens device gallery to pick an image
Selected image preview appears below the button
Tap 'Upload Image' starts upload and shows progress percentage
After upload, uploaded image from cloud is displayed below progress
Stretch Goal
Add a cancel upload button to stop the upload in progress
💡 Hint
Use the UploadTask.cancel() method from firebase_storage package and update UI accordingly

Practice

(1/5)
1. What is the main purpose of using FirebaseStorage.instance.ref() in Flutter apps?
easy
A. To initialize the Firebase app configuration.
B. To create a reference to a location in cloud storage where files can be uploaded or downloaded.
C. To display images stored in the app's local folder.
D. To authenticate users before accessing the app.

Solution

  1. Step 1: Understand FirebaseStorage.instance.ref()

    This method creates a reference to a specific location in Firebase Cloud Storage where files can be managed.
  2. Step 2: Identify its role in file handling

    It is used to point to folders or files for uploading or downloading, not for app initialization or user authentication.
  3. Final Answer:

    To create a reference to a location in cloud storage where files can be uploaded or downloaded. -> Option B
  4. Quick Check:

    ref() creates storage location reference [OK]
Hint: Remember ref() points to storage location, not app setup [OK]
Common Mistakes:
  • Confusing ref() with Firebase app initialization
  • Thinking ref() handles user authentication
  • Assuming ref() accesses local files
2. Which of the following is the correct syntax to upload a file named imageFile to Firebase Storage in Flutter?
easy
A. await FirebaseStorage.instance.ref('images/image.png').putFile(imageFile);
B. FirebaseStorage.putFile('images/image.png', imageFile);
C. await FirebaseStorage.uploadFile('images/image.png', imageFile);
D. FirebaseStorage.instance.upload('images/image.png', imageFile);

Solution

  1. Step 1: Check the correct method for uploading files

    The method to upload a file is putFile() called on a reference from FirebaseStorage.instance.ref().
  2. Step 2: Match the syntax

    await FirebaseStorage.instance.ref('images/image.png').putFile(imageFile); correctly uses await FirebaseStorage.instance.ref('path').putFile(file). Other options use incorrect method names or call patterns.
  3. Final Answer:

    await FirebaseStorage.instance.ref('images/image.png').putFile(imageFile); -> Option A
  4. Quick Check:

    Use ref().putFile() to upload [OK]
Hint: Upload files with ref(path).putFile(file) [OK]
Common Mistakes:
  • Using incorrect method names like uploadFile or upload
  • Calling putFile directly on FirebaseStorage without ref()
  • Omitting await for asynchronous upload
3. Consider the following Flutter code snippet:
final ref = FirebaseStorage.instance.ref('docs/report.pdf');
final url = await ref.getDownloadURL();
print(url);
What will be printed by this code?
medium
A. An error because getDownloadURL() requires a file upload first.
B. The local file path of 'report.pdf' on the device.
C. The binary content of the file 'report.pdf'.
D. A string URL that can be used to download the file 'report.pdf' from Firebase Storage.

Solution

  1. Step 1: Understand getDownloadURL()

    This method returns a URL string that points to the file stored in Firebase Storage at the given reference.
  2. Step 2: Analyze the code output

    The code prints the URL string, not local paths, errors, or file content.
  3. Final Answer:

    A string URL that can be used to download the file 'report.pdf' from Firebase Storage. -> Option D
  4. Quick Check:

    getDownloadURL() returns file URL [OK]
Hint: getDownloadURL() returns a downloadable URL string [OK]
Common Mistakes:
  • Thinking it returns local file path
  • Expecting file content instead of URL
  • Assuming error if file not uploaded (only if missing)
4. You wrote this code to upload a file but it throws an error:
final ref = FirebaseStorage.instance.ref('uploads/photo.jpg');
ref.putFile(photoFile);
What is the likely cause of the error?
medium
A. FirebaseStorage.instance is not initialized.
B. Using ref() instead of ref without parentheses.
C. Missing await keyword before putFile causing unhandled Future.
D. photoFile is not a valid File object.

Solution

  1. Step 1: Check asynchronous call usage

    The method putFile() returns a Future and should be awaited or handled properly.
  2. Step 2: Identify missing await

    Not using await or .then() can cause errors or unhandled Futures in Flutter async code.
  3. Final Answer:

    Missing await keyword before putFile causing unhandled Future. -> Option C
  4. Quick Check:

    Always await async upload calls [OK]
Hint: Always await putFile() to handle async upload [OK]
Common Mistakes:
  • Forgetting await on putFile()
  • Confusing ref() usage
  • Passing wrong file type without checking
5. You want to upload multiple images from a list List<File> images to Firebase Storage under folder 'gallery/'. Which approach correctly uploads all files and collects their download URLs?
hard
A. Use a loop with await inside to upload each file and then call getDownloadURL() for each upload, storing URLs in a list.
B. Upload all files without awaiting, then call getDownloadURL() once after the loop for all files.
C. Call getDownloadURL() before uploading files to get URLs in advance.
D. Upload files using putFile() without references and get URLs from local file paths.

Solution

  1. Step 1: Upload files sequentially with await

    Uploading each file with await ensures each upload completes before moving on, preventing errors.
  2. Step 2: Get download URLs after each upload

    After each upload, call getDownloadURL() on the file's reference to get its URL and store it.
  3. Step 3: Collect URLs in a list

    Store each URL in a list to use later, ensuring all files are uploaded and URLs are valid.
  4. Final Answer:

    Use a loop with await inside to upload each file and then call getDownloadURL() for each upload, storing URLs in a list. -> Option A
  5. Quick Check:

    Upload with await, then getDownloadURL() per file [OK]
Hint: Upload files one by one with await, then get URLs [OK]
Common Mistakes:
  • Not awaiting uploads causing race conditions
  • Calling getDownloadURL() before upload
  • Assuming one getDownloadURL() call returns all URLs
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard