skip to Main Content

I need help with a flutter application linked with Firebase. This application has a login method and I want to have a picture where users can update it whenever they want.

For now, I manage to replace a picture who’s already existing in a Firebase Storage’s file by a picture taken from the gallery of a phone (uploadFile). Also I can take back this picture from Firebase Storage if it’s already existing in Firebase Storage (getProfilImage).

The issue:
However, when I want to add a new picture from my application to the Firebase Storage, Firebase doesn’t allow my user to create a new file with the new picture and my app crashed.

If someone could give me a help in order to change the picture of the user without already having a file for this picture in Firebase Storage, I would appreciate

The debug console error

E/StorageException(17322): StorageException has occurred.
E/StorageException(17322): Object does not exist at location.
E/StorageException(17322):  Code: -13010 HttpResult: 404
E/StorageException(17322): {  "error": {    "code": 404,    "message": "Not Found."  }}
E/StorageException(17322): java.io.IOException: {  "error": {    "code": 404,    "message": "Not Found."  }}

The function to upload an image to Firebase Storage:
NB: The code works when $currentUser is replaced by an already existing file

 Future uploadFile() async {
    Reference storageRef = storage.ref().child('UsersImageProfil/$currentUser.png'); 
    UploadTask uploadTask = storageRef.putFile(imageProfilFile!);
    await uploadTask.whenComplete(() {
       print('File uploaded');  
      setState(() {
              imageProfilFile = null;
            });  
    });
  }

The function to get the image from Firebase Storage
NB: The code works when $currentUser is replaced by an already existing file

 void initState() {
    super.initState();
    getProfilImage();
  }

   getProfilImage() {
    Reference ref = storage.ref().child('UsersImageProfil/$currentUser.png');
    ref.getDownloadURL().then((downloadUrl) {
      setState(() {
        userPhotoUrl = downloadUrl.toString();
      });
    }).catchError((e) {
      setState(() {
        userPhotoUrl = defaultImageUrl;
      });
      print('Une erreur est survenue: ${e.error}');
    });
  }

The function who display the picture

class SetPhotoProfilState extends State<SetPhotoProfil> {
  File? imageProfilFile;
  final picker = ImagePicker();
  String? userPhotoUrl;
  String defaultImageUrl = 'https://svgsilh.com/png-1024/2098873.png';
@override
  Widget build(BuildContext context) {
    return Container(
        child: Row(
      mainAxisAlignment: MainAxisAlignment.spaceAround,
      children: [
        ElevatedButton(
            style: ButtonStyle(
                backgroundColor: MaterialStateProperty.all(kColorPrimary)),
            onPressed: () async {
              Map<Permission, PermissionStatus> statuses = await [
                Permission.storage,
                Permission.camera,
              ].request();
              if (statuses[Permission.storage]!.isGranted &&
                  statuses[Permission.camera]!.isGranted) {
                showImagePicker(context);
              } else {
                print('No permission');
              }
            },
            child: Text("Modifier sa photo de profil")),
        userPhotoUrl == null
            ? CircleAvatar(
                radius: 42,
                backgroundColor: kColorPrimary,
                child: CircleAvatar(
                  radius: 40,
                  backgroundImage: NetworkImage(
                   defaultImageUrl, // Remplacez l'URL par le lien de votre image de profil
                  ),
                ),
              )
            : CircleAvatar(
                radius: 42,
                backgroundColor: kColorPrimary,
                child: CircleAvatar(
                    radius: 40, backgroundImage: NetworkImage(userPhotoUrl!)),
              ),
      ],
    ));
  }

The showImagePicker function

  void showImagePicker(BuildContext context) {
    showModalBottomSheet(
        context: context,
        builder: (builder) {
          return Card(
            child: Container(
              width: MediaQuery.of(context).size.width,
              height: MediaQuery.of(context).size.height / 5.2,
              margin: const EdgeInsets.only(top: 8.0),
              padding: const EdgeInsets.all(12),
              child: Row(
                mainAxisAlignment: MainAxisAlignment.center,
                children: [
                  Expanded(
                    child: InkWell(
                      child: Column(
                        children: [
                          Icon(Icons.image, size: 60.0),
                          SizedBox(
                            height: 12.0,
                          ),
                          Text(
                            'Gallerie',
                            textAlign: TextAlign.center,
                          )
                        ],
                      ),
                      onTap: () {
                        _imgFromGallery();
                        Navigator.pop(context);
                      },
                    ),
                  ),

   _imgFromGallery() async {
     await picker
        .pickImage(source: ImageSource.gallery, imageQuality: 50)
        .then((value) {
      if (value != null) {
        imageCache.clear();
      setState(() {
        imageProfilFile = File(croppedFile.path);
        convertImageToPNG();
        uploadFile(); 
      });
      }
    });
  }

Also I’ve already modify the Storage rules:

service firebase.storage {
  match /b/{bucket}/o {
    match /{allPaths=**} {
      allow read, write: if request.auth != null;
    }
  }
}

2

Answers


  1. Chosen as BEST ANSWER

    I resolved my issue. It seems that the error came from the getProfilImage() function. There is the new getProfilImage() function :

    Future getProfilImage() async {
    var urlRef = storage.ref().child("UsersImageProfil").child("${currentUser.uid}");
      if (urlRef == null){
        setState((){
    userPhotoUrl = null;
        });
      }
      try{
    var imgURL = await urlRef.getDownloadURL();
     setState((){
          userPhotoUrl = imgURL;
        });
      }catch(error){
        print("erreur getProfilImage");
      }
    }
    

    I just had to put an if condition in order to help firebase storage to manage the case if there wasn't any picture yet in the storage.I also change the UploadFile function:

     Future uploadFile() async {
    Reference referenceRoot = storage.ref();
    Reference referenceDirImages = referenceRoot.child('UsersImageProfil');
    Reference referenceImageToUpload =
        referenceDirImages.child('${currentUser.uid}');
    try {
      await referenceImageToUpload.putFile(imageProfilFile!);
      referenceImageToUpload.getDownloadURL().then((value) {
        setState(() {
          userPhotoUrl = value;
        });
      });
    } catch (error) {
      print('erreur uploadFile');
    }
    

    }


  2. try updating yours with this rule

    service firebase.storage {
      match /b/{bucket}/o {
        match /{allPaths=**} {
          allow read, write: if request.auth != null; // Allow authenticated users to read and write files
          allow create: if request.auth != null && request.resource.size < 10 * 1024 * 1024; // Allow files smaller than 10 MB to be created
        }
      }
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search