Reputation: 15
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
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
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