# #flutter #url #google-cloud-firestore #storage
Вопрос:
Я пытаюсь получить URL загруженного файла изображения в хранилище firebase, но сталкиваюсь с очень странным поведением.
Пожалуйста, взгляните на приведенный ниже код, проблема объясняется в комментариях:
Futurelt;String?gt; _uploadImage(String fileName, File imageFile) async { try { // Uploading the selected image with some custom meta data await FirebaseStorage.instance .ref(fileName) .putFile( imageFile, SettableMetadata(customMetadata: { 'uploaded_by': 'Some guy', 'description': 'Some description...' })) .then((imgUploadTaskSnapshot) async { switch (imgUploadTaskSnapshot.state) { case TaskState.paused: break; case TaskState.running: break; case TaskState.success: return await FirebaseStorage.instance.ref(fileName).getDownloadURL().then((fileURL) { print('url : $fileURL'); // here i get a value -gt; url : https://firebasest..... return fileURL; // but here null is returned }); break; case TaskState.canceled: break; case TaskState.error: break; } }); } on FirebaseException catch (error) { //Todo: handle errors print(error); throw error; } } Futurelt;Listlt;Stringgt;?gt; uploadImages(Listlt;Maplt;String, dynamicgt;gt; images) async { try { Listlt;Stringgt; imgsURLs = lt;Stringgt;[]; for (int i = 0; i lt; images.length; i ) { await _uploadImage(images[i]['filename'], images[i]['imagefile']) .then((imgURL) { print('imgURL: $imgURL'); // cause here i get -gt; imgURL: null if (imgURL != null) { imgsURLs.add(imgURL); } }); } print('imgsURLs: $imgsURLs'); return imgsURLs; } on FirebaseException catch (error) { //Todo: hadle errors print(error); throw error; } }
Ответ №1:
Это происходит потому, что тело в then
обратном вызове-это другая функция. Таким образом, вызов return
внутри него вернет значение, но не для _uploadImage
, а для анонимного обратного вызова.
Возвращенное значение фактически появится в результате ожидания обратного вызова. Вы можете добавить возврат, чтобы в дальнейшем вернуть его в результате _uploadImage
return await FirebaseStorage.instance.ref(fileName).getDownloadURL().then(...
Что также стоит отметить, так это то, что вам не нужно использовать then
, когда вы находитесь в асинхронной функции. Это главное преимущество их наличия — вам не нужно иметь дело с обратными вызовами.
Futurelt;String?gt; _uploadImage(String fileName, File imageFile) async { try { // Uploading the selected image with some custom meta data final imgUploadTaskSnapshot = await FirebaseStorage.instance .ref(fileName) .putFile( imageFile, SettableMetadata(customMetadata: { 'uploaded_by': 'Some guy', 'description': 'Some description...' })); switch (imgUploadTaskSnapshot.state) { case TaskState.paused: break; case TaskState.running: break; case TaskState.success: final fileURL = await FirebaseStorage.instance.ref(fileName).getDownloadURL(); return fileURL; case TaskState.canceled: break; case TaskState.error: break; } } on FirebaseException catch (error) { //Todo: handle errors print(error); throw error; } }
Комментарии:
1. Большое спасибо за ваш ответ. Я уверен, что это поможет. Я просто на самом деле отсутствую несколько дней, поэтому я подожду, пока вернусь, чтобы проверить свое приложение, прежде чем закрыть тему. Еще раз большое спасибо
2. Привет, pr0gramist, я изменил код, как вы предложили, но у меня все еще тот же результат.
3. Трудно догадаться, что может быть не так. Вы можете обновить код или явно добавить типы, чтобы определить проблему.