Я пытаюсь загрузить изображение из своего приложения Flutter в хранилище Firebase.
final _avatars = AvatarService();
Future _pickImage(BuildContext context) async{
final img = await ImagePicker().pickImage(source: ImageSource.gallery);
if (img == null) return;
try {
await _avatars.saveAvatar(_auth.getCurrentUser()!.uid.toString(), File(img.path));
avatar = await _avatars.getAvatar(_auth.getCurrentUser()!.uid.toString());
setState(() {
});
}
catch(e){
showDialog(context: context, builder: (context) => AlertDialog(
title: Text(e.toString())
));
}
}
import 'dart:io';
import 'dart:typed_data';
import 'package:firebase_storage/firebase_storage.dart';
class AvatarService{
Future saveAvatar(String uid, File file) async{
final storageRef = FirebaseStorage.instance.ref();
final imgRef = storageRef.child("$uid.jpg");
await imgRef.putFile(file);
}
Future<Uint8List?> getAvatar(String uid) async{
final storageRef = FirebaseStorage.instance.ref();
final imageRef = storageRef.child("$uid.jpg");
Uint8List? avatar;
try{
avatar = await imageRef.getData();
}
catch(e){
print(e);
}
return avatar;
}
}
Но когда я загружаю свою фотографию, мое приложение просто отключается, и у меня нет изображения в хранилище Firebase. Я также пытался загрузить изображение таким образом =>
final _avatars = AvatarService();
Future _pickImage(BuildContext context) async{
final img = await ImagePicker().pickImage(source: ImageSource.gallery);
if (img == null) return;
try {
await _avatars.saveAvatar(_auth.getCurrentUser()!.uid.toString(), File(img.path).readAsBytes);
avatar = await _avatars.getAvatar(_auth.getCurrentUser()!.uid.toString());
setState(() {
});
}
catch(e){
showDialog(context: context, builder: (context) => AlertDialog(
title: Text(e.toString())
));
}
}
class AvatarService{
Future saveAvatar(String uid, Uint8List imageBytes) async{
final storageRef = FirebaseStorage.instance.ref();
final imgRef = storageRef.child("$uid.jpg");
await imgRef.putData(imageBytes);
}
Future<Uint8List?> getAvatar(String uid) async{
final storageRef = FirebaseStorage.instance.ref();
final imageRef = storageRef.child("$uid.jpg");
Uint8List? avatar;
try{
avatar = await imageRef.getData();
}
catch(e){
print(e);
}
return avatar;
}
}
А также пытался изменить File(img.path).readAsBytes на img.readAsBytes, но в обеих попытках я получил только неправильный файл размера 32b, а не изображение, которое загружал.
Пожалуйста, скажите мне, что я делаю неправильно.





Рекомендуется работать с файлом, а не передавать байтовые данные.
А при получении данных вы можете использовать getDownloadUrl вместо getData.
пожалуйста, рассмотрите возможность изменения кода вашего аватара:
import 'dart:io';
import 'package:firebase_storage/firebase_storage.dart';
class AvatarService {
Future<String?> saveAvatar(String uid, File imageFile) async {
try {
final storageRef = FirebaseStorage.instance.ref();
final imageRef = storageRef.child("$uid.jpg");
await imageRef.putFile(imageFile);
return await imageRef.getDownloadURL();
} catch (e) {
print('ERROR (saveAvatar) = ${e.toString()}');
return null;
}
}
Future<String?> getAvatar(String uid) async {
try {
final storageRef = FirebaseStorage.instance.ref();
final imageRef = storageRef.child("$uid.jpg");
return await imageRef.getDownloadURL();
} catch (e) {
print('ERROR (getAvatar) = ${e.toString()}');
return null;
}
}
}
А метод выбора должен выглядеть так:
File? pickImage(ImageSource src) async {
final XFile? pickedImageFile =
await _picker.pickImage(source: src);
if (pickedImageFile != null) {
return File(pickedImageFile.path);
} else {
print('ERRRO (pickImage) = No image selected');
}
}
Примечание:
вызовите метод pickImage(ImageSource.gallery), если хотите выбрать из галереи.
вызовите метод pickImage(ImageSource.camera), если хотите выбрать с камеры.
Здравствуйте. Спасибо за быстрый ответ. Не могли бы вы предоставить мне более подробную информацию о сообщении об ошибке, которое вы получаете? Вы запускаете это на эмуляторе IOS, Android или в Интернете? Правильно ли вы настроили свой пакет хранилища Firebase? все эти детали помогают мне определить правильное решение для вас. Спасибо
Я работаю в Windows. в консоли отладки у меня есть сообщение «Потеряно соединение с устройством. Выход».
Я думаю, что проблема связана с ограничением платформы image_picker. Рассмотрите возможность использования file_selector для выбора файлов с платформы Windows.
Нет, я тестировал image_picker без загрузки изображений в хранилище Firebase, и он работал без проблем. Проблема именно в загрузке хранилища Firebase. Выбор и загрузка изображений из хранилища Firebase работают правильно.
Остается только одна возможность проверить, может ли это решить вашу проблему: настроили ли вы правила доступа к хранилищу Firebase? если да, то откройте проблему в вопросах GitHub.
Вот мои правила хранения в Firebase: "rules_version = '2'; // Создаем правила на основе данных в вашей базе данных Firestore // разрешаем запись: if firestore.get( // /databases/(default)/documents/users/$( request.auth.uid)).data.isAdmin; service firebase.storage { match /b/{bucket}/o { match /{allPaths=**} { разрешить чтение, запись: если true;
$(request.auth.uid)).data.isAdmin что вы подразумеваете под этим состоянием
вот версия, которая проверяет пользователя, является ли он администратором из коллекции пользователей rules_version = '2'; service firebase.storage { match /b/{bucket}/o { // Match all paths in the storage bucket match /{allPaths=**} { // Allow read access only for authenticated users allow read: if request.auth != null; // Allow write access if the user is an admin allow write: if request.auth != null && firestore.get(/databases/$(database)/documents/users/$(request.auth.uid)).data.isAdmin == true; } } }
Я изменил putFile на putData и запустил на Android, все работало правильно. Но в Windows я получаю неверный файл и эту ошибку в консоли отладки: [ОШИБКА: flutter/shell/common/shell.cc(1038)] Канал 44d4-a040-0084dc0a5740' отправил сообщение от родного к Flutter в неплатформенной ветке. Сообщения канала платформы должны отправляться в поток платформы. Невыполнение этого требования может привести к потере данных или сбоям и должно быть исправлено в коде плагина или приложения, создающего этот канал.
Привет, спасибо за советы, но моя проблема заключается в загрузке файла в хранилище Firebase, а не в загрузке из него. Как я уже писал ранее, когда я пытаюсь выполнить putFile, мое приложение просто вылетает. Когда я пытаюсь «putData», я получил неверный файл в хранилище Firebase.