VladofCM
VladofCM

Reputation: 15

Error when saving Document to Firebase Cloud Database in Flutter

I have a database service which performs the following actions:

class DatabaseService {

  final String uid;
  DatabaseService({this.uid});
  //collection reference
  final CollectionReference userCollection = Firestore.instance.collection('users');

  //USER METHODS
  //update user data
  Future updateUserData(String username, int colorData, String avatar) async {
    return await userCollection.document(uid).setData(
      {
        'username': username,
        'color': colorData,
        'avatar': avatar
      }
    );
  }

The data is sent from the following form:

class SettingsForm extends StatefulWidget {
  SettingsForm({Key key}) : super(key: key);

  @override
  _SettingsFormState createState() => _SettingsFormState();
}

class _SettingsFormState extends State<SettingsForm> {
  final _formKey = GlobalKey<FormState>();

  //form values
  String _currentUsername;
  int _currentColor;
  String _currentAvatar;
  File _avatarFile;

  //avatar picker
  Future chooseAvatar() async { 
    File image = await ImagePicker.pickImage(source: ImageSource.gallery);
    setState(() {
      _avatarFile = image;
    });
  }

  @override
  Widget build(BuildContext context) {
    final user = Provider.of<User>(context);
    return StreamBuilder<UserData>(
      stream: DatabaseService(uid: user.uid).userData,
      builder: (context, snapshot) {
        if(snapshot.hasData){
          UserData userData = snapshot.data;
          if(_currentColor == null){
            _currentColor = userData.colorData;
          }
          avatarColor = Color(_currentColor);
          return Form(
            key: _formKey,
            child: Column(
              children: <Widget>[
                Row(
                  children: <Widget>[
                    FlatButton.icon(
                      label: Text("Save"),
                      icon: Icon(Icons.save),
                      onPressed: () async {
                      if(_formKey.currentState.validate()){
                        String url = await StorageService().addOrUpdateUser(_avatarFile, user.uid, currentFileUrl: userData.avatar);
                        setState(() => _currentAvatar = url);
                        await DatabaseService(uid: user.uid).updateUserData(
                          _currentUsername ?? userData.username, 
                          _currentColor ?? userData.color(), 
                          _currentAvatar ?? userData.avatar
                          );
                          Navigator.pop(context);
                        }
                      },
                    ),
                  ],
                ),
                ListView(
                  children: <Widget>[
                    TextFormField(
                      initialValue: userData.username,
                      onChanged: (val) => setState(() => _currentUsername = val),
                    ),
                  Container(
                    child: _avatarFile == null ?
                        Column(
                          children: <Widget>[
                            ButtonTheme(
                              minWidth: double.infinity,
                              child: RaisedButton.icon(
                                label: Text("Upload Avatar"),
                                icon: Icon(Icons.photo_library),
                                elevation: 10,
                                onPressed: chooseAvatar,
                              ),
                            ),
                          ],
                        )
                        : Column(
                          children: <Widget>[
                            ButtonTheme(
                              minWidth: double.infinity,
                              child: RaisedButton.icon(
                                label: Text("Remove Avatar"),
                                icon: Icon(Icons.close),
                                onPressed: () => setState(()=> _avatarFile = null),
                              ),
                            ),
                          ],
                        ),
                    ),
                  ]
                ),
              ],
            )
          );
        }
        else{
          return Loading();
        }
      }
    );
  }
}

The Storage Service is doing the following:

class StorageService{
  final _storage = FirebaseStorage.instance;

  final _users = FirebaseStorage.instance.ref().child("/Users/");

  Future<String> addOrUpdateUser(File image, String fileName, {String   currentFileUrl}) async {
    String imageName = fileName + Path.extension(image.path);
    StorageReference ref = _users.child(imageName);
    StorageUploadTask task = ref.putFile(image);
    String url = await (await task.onComplete).ref.getDownloadURL();
    print("in Storage");
    print(url);

    deleteImage(currentFileUrl);

    return url;
  }
  Future deleteImage(String currentFileUrl) async {
    final _oldRef = await _storage.getReferenceFromUrl(currentFileUrl);
    return _oldRef.delete();
  }

I know from the copy/paste there is some imbalance to the braces and such but the code does compile and run.

Once the image is uploaded to the Firebase Storage the Download URL is correctly delivered back to the widget and the state is successfully updated. Once the username, color and avatar are sent to the Database service I have shown that the data is delivered properly.

for reasons unknown to me the application is exiting at this point before updating the user document and the terminal is showing the following error:

flutter: in Storage
flutter: https://firebasestorage.googleapis.com/v0/b/xxx-yyy.appspot.com/o/Users%2FpVVUiVsWfudo6NNpr9yQEgfc2tD2.jpg?alt=media&token=0a0a373a-f5be-41f1-9b23-86ad78cdd91c
flutter: In database
flutter: https://firebasestorage.googleapis.com/v0/b/xxx-yyy.appspot.com/o/Users%2FpVVUiVsWfudo6NNpr9yQEgfc2tD2.jpg?alt=media&token=0a0a373a-f5be-41f1-9b23-86ad78cdd91c
Lost connection to device.
*** First throw call stack:
(
        0   CoreFoundation                      0x00007fff23c4f02e __exceptionPreprocess + 350
        1   libobjc.A.dylib                     0x00007fff50b97b20 objc_exception_throw + 48
        2   CoreFoundation                      0x00007fff23c4ee6c +[NSException raise:format:] + 188
        3   Runner                              0x000000010e7a330e +[FIRStoragePath pathFromString:] + 318
        4   Runner                              0x000000010e797458 -[FIRStorage referenceForURL:] + 88
        5   Runner                              0x000000010e858f94 -[FLTFirebaseStoragePlugin getReferenceFromUrl:result:] + 212
        6   Runner                              0x000000010e857690 -[FLTFirebaseStoragePlugin handleMethodCall:result:] + 1536
        7   Flutter                             0x00000001103abf95 __45-[FlutterMethodChannel setMethodCallHandler:]_block_invoke + 104
        8<…>

Any help would be appreciated!!!

Upvotes: 0

Views: 523

Answers (2)

VladofCM
VladofCM

Reputation: 15

Thanks for the help everyone. turns out I had made a simple mistake and was trying to save a type Color variable into the firebasecloud which apparently didn't like it, not its back to normal uploading the integer color code.

Upvotes: 1

Jay Mungara
Jay Mungara

Reputation: 7148

Just change your image upload method as follow,

Future<String> addOrUpdateUser(File image, String fileName, {String   currentFileUrl}) async {
    String imageName = fileName + Path.extension(image.path);
    StorageReference ref = _users.child(imageName);
    StorageUploadTask task = ref.putFile(image);

    StorageTaskSnapshot taskSnapshot = await uploadTask.onComplete;
    String url = await taskSnapshot.ref.getDownloadURL();

    deleteImage(currentFileUrl);

    return url;
  }

Upvotes: 0

Related Questions