flutter firebase: Update a field with image url

247 Views Asked by At

How do I update a field in a collection with image url? I can update with other strings but the image url doesn't seem to work. I first upload this image imageUrl in a different subcollection called "Documents". It works. I want to use the same imageUrl to UPDATE it's parent collection called 'users' with the field 'Document'. but it doesn't work. Any help?

File? image;
  String? imageUrl = "";
  String uid = FirebaseAuth.instance.currentUser!.uid;
  Future<File> customCompressed(
      {required File imagePathToCompress,
      quality = 100,
      percentage = 10}) async {
    var path = await FlutterNativeImage.compressImage(
        imagePathToCompress.absolute.path,
        quality: 100,
        percentage: 80);
    return path;
  }

  Future<File?> pickImages() async {
    File? image;
    try {
      final pickedImage =
          await ImagePicker().pickImage(source: ImageSource.camera);
      if (pickedImage != null) {
        image = File(pickedImage.path);
        File compressedImage =
            await customCompressed(imagePathToCompress: image);
        setState(() {
          image = compressedImage;
        });
      }
    } catch (e) {
      showSnackBar(context, e.toString());
    }
    return image;
  }

  upload() async {
    final authProvider = Provider.of<AuthProvider>(context, listen: false);

    String uid = FirebaseAuth.instance.currentUser!.uid;

    var imageFile = File(image!.path);

    FirebaseStorage storage = FirebaseStorage.instance;
    Reference ref = storage.ref().child("Document").child(uid);

    UploadTask uploadTask = ref.putFile(imageFile);
    await uploadTask.whenComplete(() async {
      var url = await ref.getDownloadURL();
      imageUrl = url.toString();
    }).catchError((onError) {
      return onError;
    });

    Map<String, dynamic> getdata = {
      "document": imageUrl,
      "Full name": authProvider.userModel.fullName,
      "Email": authProvider.userModel.email,
      
    };
    CollectionReference collectionReference = FirebaseFirestore.instance
        .collection('users')
        .doc(uid)
        .collection('Documants');

    collectionReference.add(getdata);
  }

  // for selecting image
  void selectImage() async {
    image = await pickImages();
  }

  CollectionReference ref = FirebaseFirestore.instance.collection('users');

TextButton(onPressed: () { upload();
ref.doc(uid).update({'Status': 'Pending verification'});
ref.doc(uid).update({'Document': imageUrl});
 },
 child: const Text('Upload document',
style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold),))
1

There are 1 best solutions below

2
Roque Barragan On

To update a document, you must first create it. Then, if you want to update the value, you must perform the same action again.

Here is your code with a few modifications. The important part is that if you want to update an existing document instead of creating a new one, you need to pass an enum with the "update" operation. In the function, I retrieve the previous document ID and use the update function to modify it.

I hope it helps you. Regards. Btw, sorry if my English is not the best.

Future<void> upload({required OperationType operationType}) async {
  final authProvider = Provider.of<AuthProvider>(context, listen: false);

  final String uid = FirebaseAuth.instance.currentUser!.uid;

  final imageFile = File(image!.path);
  String? imageUrl;

  final FirebaseStorage storage = FirebaseStorage.instance;
  final Reference ref = storage.ref().child("Document").child(uid);
  final UploadTask uploadTask = ref.putFile(imageFile);
  await uploadTask.whenComplete(() async {
    final url = await ref.getDownloadURL();
    imageUrl = url;
  }).catchError((onError) {
    return onError;
  });

  final Map<String, dynamic> getdata = {
    "user_id": uid,
    "document": imageUrl,
    "full_name": authProvider.userModel.fullName,
    "email": authProvider.userModel.email,
  };
  final CollectionReference collectionReference = FirebaseFirestore.instance
      .collection('users')
      .doc(uid)
      .collection('Documants');
  if (operationType == OperationType.create) {
    await collectionReference.add(getdata);
  } else {
//Update
//Here, you need to retrieve the previously created file in order to update it.
//If you already have the value, you can pass it as an argument to the function, such as "String? docId".
    final documents = await collectionReference
        .where("user_id", isEqualTo: uid)
        .limit(1)
        .get();
    if (documents.docs.isNotEmpty) {
      final previousDocId = documents.docs[0].id;
      await collectionReference.doc(previousDocId).update(getdata);
    } else {
      // Throws Some exception because didnt find previous value
      throw Exception();
    }
  }
}