0
0
Fluttermobile~20 mins

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

Choose your learning style9 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