1

I'm currently stuck at where I'm trying to upload image to Firestore Storage and automatically store the image URL to Cloud Firestore. I have tried to manually upload the image to Firebase Storage and pasting the image url to Cloud Firestore then retrieving it to show the image in my app and it works. Heres the coding that I have done so far:

models/enter.dart

 class Enter { final String enterId; final String enter; final String price; final String url; Enter({this.enter, this.price, @required this.enterId, this.url}); factory Enter.fromJson(Map<String, dynamic> json){ return Enter( enter: json['enter'], price: json['price'], url: json['url'], enterId: json['enterId'] ); } Map<String,dynamic> toMap(){ return { 'enter':enter, 'price':price, 'url':url, 'enterId':enterId }; } } 

services/firestore_service2

import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:journal_app/src/models/enter.dart'; class FirestoreService2 { FirebaseFirestore _db = FirebaseFirestore.instance; //Get Entries Stream<List<Enter>> getEnter(){ return _db .collection('enters') .snapshots() .map((snapshot) => snapshot.docs .map((doc) => Enter.fromJson(doc.data())) .toList()); } //Upsert Future<void> setEnter(Enter enter){ var options = SetOptions(merge:true); return _db .collection('enters') .doc(enter.enterId) .set(enter.toMap(),options); } //Delete Future<void> removeEnter(String enterId){ return _db .collection('enters') .doc(enterId) .delete(); } } 

provider/enter_provider.dart

import 'package:flutter/material.dart'; import 'package:journal_app/src/models/enter.dart'; import 'package:journal_app/src/services/firestore_service2.dart'; import 'package:uuid/uuid.dart'; class EnterProvider with ChangeNotifier { final firestoreService = FirestoreService2(); String _enter; String _price; String _enterId; String _url; var uuid = Uuid(); //Getters String get enter => _enter; String get price => _price; String get url => _url; Stream<List<Enter>> get enters => firestoreService.getEnter(); //Setters set changeEnter(String enter){ _enter = enter; notifyListeners(); } set changePrice(String price){ _price = price; notifyListeners(); } set changeUrl(String url){ _url = url; notifyListeners(); } //Functions loadAll(Enter enter){ if (enter != null && price != null){ _enter =enter.enter; _price =enter.price; _url=enter.url; _enterId = enter.enterId; } else { _enter = null; _price = null; _url = null; _enterId = null; } } saveEnter(){ if (_enterId == null){ //Add var newEnter = Enter(enter: _enter, price: _price, url: _url, enterId: uuid.v1()); print(newEnter.enter); print(newEnter.price); print(newEnter.url); firestoreService.setEnter(newEnter); } else { //Edit var updatedEnter = Enter(enter: _enter, price: _price, url: _url, enterId: _enterId); firestoreService.setEnter(updatedEnter); } } removeEnter(String enterId){ firestoreService.removeEnter(enterId); } } 

screens/enter.dart where user insert product name, price and image

import 'package:date_format/date_format.dart'; import 'package:flutter/material.dart'; import 'package:journal_app/src/models/enter.dart'; import 'package:journal_app/src/providers/enter_provider.dart'; import 'package:provider/provider.dart'; class EnterScreen extends StatefulWidget { final Enter enter; final Enter price; final Enter category; EnterScreen({this.enter, this.price, this.category}); @override _EnterScreenState createState() => _EnterScreenState(); } class _EnterScreenState extends State<EnterScreen> { final enterController = TextEditingController(); final enterController2 = TextEditingController(); @override void dispose() { enterController.dispose(); enterController2.dispose(); super.dispose(); } @override void initState() { final enterProvider = Provider.of<EnterProvider>(context,listen: false); if (widget.enter != null){ //Edit enterController.text = widget.enter.enter; enterController2.text = widget.enter.price; enterProvider.loadAll(widget.enter); enterProvider.loadAll(widget.price); } else { //Add enterProvider.loadAll(null); } super.initState(); } @override Widget build(BuildContext context) { final enterProvider = Provider.of<EnterProvider>(context); return Scaffold( appBar: AppBar(title: Text('Products')), body: Padding( padding: const EdgeInsets.all(8.0), child: ListView( children: [ TextField( decoration: InputDecoration( labelText: 'Product Name', border: InputBorder.none, ), style: TextStyle(color: Colors.black, fontSize: 25), maxLines: 5, minLines: 2, onChanged: (String value) => enterProvider.changeEnter = value, controller: enterController, ), TextField( decoration: InputDecoration( labelText: 'Product Price', border: InputBorder.none, ), style: TextStyle(color: Colors.black, fontSize: 25), maxLines: 5, minLines: 2, onChanged: (String value) => enterProvider.changePrice = value, controller: enterController2, ), RaisedButton( color: Theme.of(context).accentColor, child: Text('Save',style: TextStyle(color: Colors.white, fontSize: 20)), onPressed: () { enterProvider.saveEnter(); Navigator.of(context).pop(); }, ), (widget.enter != null) ? RaisedButton( color: Colors.red, child: Text('Delete',style: TextStyle(color: Colors.white, fontSize: 20)), onPressed: () { enterProvider.removeEnter(widget.enter.enterId); Navigator.of(context).pop(); }, ): Container(), ], ), ), ); } } 

screens/product.dart where this screen show the product name, price and image in listview

import 'package:date_format/date_format.dart'; import 'package:flutter/material.dart'; import 'package:journal_app/src/models/enter.dart'; import 'package:journal_app/src/providers/enter_provider.dart'; import 'package:journal_app/src/screens/enter.dart'; import 'package:provider/provider.dart'; class ProductScreen extends StatelessWidget { @override Widget build(BuildContext context) { final enterProvider = Provider.of<EnterProvider>(context); return Scaffold( appBar: AppBar( title: Text('Products'), ), body: StreamBuilder<List<Enter>>( stream: enterProvider.enters, builder: (context, snapshot) { return ListView.builder( itemCount: snapshot.data.length, itemBuilder: (context, index) { return ListTile( leading: Image.network( snapshot.data[index].url, width: 100, height: 100, fit: BoxFit.fitWidth, ), trailing: Icon(Icons.edit, color: Theme.of(context).accentColor), title: Text( snapshot.data[index].enter, style: TextStyle(fontSize: 25), ), subtitle: Text( snapshot.data[index].price, ), onTap: () { Navigator.of(context).push(MaterialPageRoute( builder: (context) => EnterScreen(enter: snapshot.data[index], price: snapshot.data[index]))); }, ); }); }), floatingActionButton: FloatingActionButton( child: Icon(Icons.add), onPressed: () { Navigator.of(context) .push(MaterialPageRoute(builder: (context) => EnterScreen())); }, ), ); } } 

The goal is to upload image to Firebase Storage, storing the image url at the same time when uploading new image.

I need advice for this project.

1
  • I did this a while before. When you are storing your image file after successfully uploading your image you need to get the image download URL and then you can save your image URL to Cloud Firestore. thats it. Commented Mar 18, 2021 at 4:30

2 Answers 2

2

In order to upload image to Firebase Storage & save it in Cloud Firestore, you need to do the following:

Step 1: Get the image that you want to upload For this, you can use the image_picker package It will give you a PickedFile object (let's say it pickedFile). Convert this object to a File object by using this code:

final file = File(pickedFile.path); 

Step 2: Upload this file to Firebase Storage: Give the image that you want to upload a unique name.

final imageName = '${DateTime.now().millisecondsSinceEpoch}.png'; 

Create Firebase Storage Reference:

final firebaseStorageRef = FirebaseStorage.instance .ref() .child('images/$imageName'); // This will create a images directory in Firebase storage & save your image in that directory 

Start uploading image:

final uploadTask = firebaseStorageRef.putFile(file); final taskSnapshot = await uploadTask.onComplete; 

Get the image URL:

final _fileURL = await taskSnapshot.ref.getDownloadURL(); 

Save this image URL in Cloud Firestore.

// This will save the image in "images" collection & update the "uploadedImage" value of document with id the same as the value of "id" variable. await FirebaseFirestore.instance.collection(images).doc(id).update({'uploadedImage': _fileURL}); 

If you are updating an existing object then use the update method or else you can use the set method.

Sign up to request clarification or add additional context in comments.

Comments

0

In your case you must follow bellow steps

  1. First upload your image to Firebase Storage and get the download URL
  2. Now you have the download URL and you can Upload your Enter object to Cloud FireStore with the url

Bellow method shows how could you store the image and get the download url list

 Future<String> uploadImage(var imageFile ) async { StorageReference ref = storage.ref().child("/photo.jpg"); StorageUploadTask uploadTask = ref.putFile(imageFile); var dowurl = await (await uploadTask.onComplete).ref.getDownloadURL(); url = dowurl.toString(); return url; } 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.