Firebase Storage putFile/putData не работает

Я пытаюсь загрузить изображение из своего приложения 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, а не изображение, которое загружал.

Пожалуйста, скажите мне, что я делаю неправильно.

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
0
79
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Рекомендуется работать с файлом, а не передавать байтовые данные. А при получении данных вы можете использовать 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), если хотите выбрать с камеры.

Привет, спасибо за советы, но моя проблема заключается в загрузке файла в хранилище Firebase, а не в загрузке из него. Как я уже писал ранее, когда я пытаюсь выполнить putFile, мое приложение просто вылетает. Когда я пытаюсь «putData», я получил неверный файл в хранилище Firebase.

Vitaliy 18.05.2024 01:08

Здравствуйте. Спасибо за быстрый ответ. Не могли бы вы предоставить мне более подробную информацию о сообщении об ошибке, которое вы получаете? Вы запускаете это на эмуляторе IOS, Android или в Интернете? Правильно ли вы настроили свой пакет хранилища Firebase? все эти детали помогают мне определить правильное решение для вас. Спасибо

dzmoxn 18.05.2024 01:23

Я работаю в Windows. в консоли отладки у меня есть сообщение «Потеряно соединение с устройством. Выход».

Vitaliy 18.05.2024 02:34

Я думаю, что проблема связана с ограничением платформы image_picker. Рассмотрите возможность использования file_selector для выбора файлов с платформы Windows.

dzmoxn 18.05.2024 13:46

Нет, я тестировал image_picker без загрузки изображений в хранилище Firebase, и он работал без проблем. Проблема именно в загрузке хранилища Firebase. Выбор и загрузка изображений из хранилища Firebase работают правильно.

Vitaliy 18.05.2024 18:42

Остается только одна возможность проверить, может ли это решить вашу проблему: настроили ли вы правила доступа к хранилищу Firebase? если да, то откройте проблему в вопросах GitHub.

dzmoxn 18.05.2024 18:49

Вот мои правила хранения в Firebase: "rules_version = '2'; // Создаем правила на основе данных в вашей базе данных Firestore // разрешаем запись: if firestore.get( // /databases/(default)/documents/users/$( request.auth.uid)).da‌​ta.isAdmin; service firebase.storage { match /b/{bucket}/o { match /{allPaths=**} { разрешить чтение, запись: если true;

Vitaliy 18.05.2024 19:59
$(request.auth.uid)).data.isAdmin что вы подразумеваете под этим состоянием
dzmoxn 19.05.2024 02:00

вот версия, которая проверяет пользователя, является ли он администратором из коллекции пользователей 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/$(reque‌​st.auth.uid)).data.i‌​sAdmin == true; } } }

dzmoxn 19.05.2024 02:01

Я изменил putFile на putData и запустил на Android, все работало правильно. Но в Windows я получаю неверный файл и эту ошибку в консоли отладки: [ОШИБКА: flutter/shell/common/shell.cc(1038)] Канал 44d4-a040-0084dc0a5‌​740' отправил сообщение от родного к Flutter в неплатформенной ветке. Сообщения канала платформы должны отправляться в поток платформы. Невыполнение этого требования может привести к потере данных или сбоям и должно быть исправлено в коде плагина или приложения, создающего этот канал.

Vitaliy 19.05.2024 21:29

Другие вопросы по теме

Ошибка: [auth/missing-client-identifier] В этом запросе отсутствует действительный идентификатор приложения, проверки целостности Play и проверки reCAPTCHA не увенчались успехом
Можно ли настроить Firebase так, чтобы при отключении пользователя срок действия его токена истекал?
Получил тот же ответ от Firestore при получении данных с помощью startAfter
Аргумент типа "EnvironmentProviders" нельзя назначить параметру типа "ImportProvidersSource".ts(2345) в проекте Angular Firebase
Войдите с помощью Google в Firebase, используя новый API диспетчера учетных данных
Init Genkit Firebase не поддерживается
Firebase: Gemini API с использованием Vertex AI – Ограничьте использование пользователями клиентского API
Как я могу использовать сообщения проверки активности, чтобы обнаружить пользователя, отключенного от игрового приложения?
Ошибка развертывания функции Google Cloud с триггером Firestore с использованием Eventarc в gcloud
Циклическая зависимость между следующими задачами после обновления плагина Gradle и плагина Firebase Crashlytics