개발노트

52. [Flutter] Firebase Storage 이용하기 (파일 업로드) 본문

앱 개발/Flutter

52. [Flutter] Firebase Storage 이용하기 (파일 업로드)

mroh1226 2024. 1. 5. 16:51
반응형

이미지, 동영상, 텍스트 등 파일업로드를 하기 위해 Firebase의 Storage 기능을 사용합니다.

Firebase Storage 소개

Firebase Storage는 사용자의 파일을 안전하게 저장하고 제공하기 위한 클라우드 저장소 서비스입니다. 주로 이미지, 비디오, 오디오, 문서 등과 같은 다양한 형식의 파일을 관리할 수 있습니다. Firebase Storage를 사용하면 서버 관리 없이 손쉽게 파일을 업로드하고 다운로드할 수 있습니다.

Firebase Storage의 주요 기능

1. 보안 규칙 설정

Firebase Storage는 보안을 강화하기 위해 규칙 기반의 접근 제어를 제공합니다. 파일에 대한 읽기 및 쓰기 권한을 정의하여 불필요한 액세스를 방지할 수 있습니다.

2. 업로드 및 다운로드

Firebase Storage를 사용하면 클라이언트 측에서 간단하게 파일을 업로드하고 다운로드할 수 있습니다. SDK를 통해 제공되는 간단한 API를 활용하면 몇 줄의 코드만으로도 파일 업로드 및 다운로드 기능을 구현할 수 있습니다.

3. 이미지 리사이징 및 썸네일 생성

Firebase Storage는 이미지 리사이징과 썸네일 생성 기능을 제공하여 사용자가 업로드한 이미지를 자동으로 최적화할 수 있습니다. 이를 통해 네트워크 대역폭을 절약하고 웹 또는 앱의 성능을 향상시킬 수 있습니다.

4. Firebase 프로젝트와의 통합

Firebase Storage는 다른 Firebase 서비스들과 쉽게 통합됩니다. 예를 들어, Firebase Authentication과 연동하여 인증된 사용자만이 파일에 접근할 수 있도록 설정할 수 있습니다.


Firebase 콜솔에서의 Storage 사용 모습.

Storage 폴더들
avatars 폴더 안에 저장된 File들

 


시작 전 세팅.

먼저, 아래 포스팅과 같이 Storage 기능을 활성화합니다.

- 설정하는 방법: https://mroh1226.tistory.com/159

 

6. [Firebase] Firestore, Storage 시작하기

Firestore: 실시간 NoSQL 데이터베이스 특징: 1. 실시간 업데이트 Firestore는 실시간으로 데이터베이스의 변경 사항을 감지하고, 이를 연결된 모든 클라이언트에 자동으로 전달합니다. 이로써 앱은 항

mroh1226.tistory.com

 

Flutter 프로젝트에 Storage를 설치합니다.

- 설치링크: https://pub.dev/packages/firebase_storage

 

firebase_storage | Flutter Package

Flutter plugin for Firebase Cloud Storage, a powerful, simple, and cost-effective object storage service for Android and iOS.

pub.dev


예시소스.

구현목표: 버튼을 클릭하여 사진을 찍고, 촬영된 이미지 File을 Firebase Storage에 업로드하는 기능을 구현한다.

Storage Repository
class StorageRepository {
  //Storage를 사용하시위해 FirebaseStorage instance를 선언
  final FirebaseStorage _firebaseStorage = FirebaseStorage.instance;

  //Avatar로 사용될 File과 파일명을 파라미터로 받아 upload하는 메소드
  Future<void> uploadAvatarImage(File file, String fileName) async {
    //Firebase Storage에 접근하고 이 폴더 link를 가리키는 Reference를 가져옴
    final fileRef = _firebaseStorage.ref().child("avatar_image/$fileName");
    //Reference에 file을 넣음
    await fileRef.putFile(file);
  }
}

final storageRepoProvider = Provider((ref) => StorageRepository());
ViewModel
class AvatarImageViewModel extends AsyncNotifier<void> {
  late final StorageRepository _storageRepository;
  @override
  FutureOr<void> build() {
    //Storage Repository를 Provider로 초기화
    _storageRepository = ref.read(storageRepoProvider);
  }

  //AvatarImage 업로드 메소드 파일명은 날짜
  Future<void> uploadAvatarImage(File file) async {
    //upload하는 동안 state를 loading 상태로 변경
    state = const AsyncValue.loading();
    //파일명을 날짜로 받음
    final filename = DateTime.now().toString();
    //data 예외처리를 위해 guard를 사용
    state = await AsyncValue.guard(() async {
      //StorageRepository의 uploadAvatarImage 메소드에 file과 filename을 주고 호출
      await _storageRepository.uploadAvatarImage(file, filename);
    });
  }
}

final avatarImageProvider = AsyncNotifierProvider<AvatarImageViewModel, void>(
  () => AvatarImageViewModel(),
);
View
class TestScreen extends ConsumerStatefulWidget {
  const TestScreen({super.key});

  @override
  ConsumerState<ConsumerStatefulWidget> createState() => _TestScreenState();
}

class _TestScreenState extends ConsumerState<TestScreen> {
  //CircleAvatar 클릭했을 때 메소드
  Future<void> tapAvatar() async {
    //ImagePicker로 받아온 file을 받아옴
    final xfile = await ImagePicker().pickImage(
        source: ImageSource.camera,
        imageQuality: 40,
        maxHeight: 150,
        maxWidth: 150);
    if (xfile != null) {
      final file = File(xfile.path);
      //avatarImageProvider로 ViewModel에 있는 uploadAvatarImage에 file을 넘겨주고 호출
      ref.read(avatarImageProvider.notifier).uploadAvatarImage(file);
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: GestureDetector(
          onTap: () => tapAvatar(),
          child: CircleAvatar(
            backgroundColor: Colors.red.shade300,
            radius: 100,
          ),
        ),
      ),
    );
  }
}

빌드된 모습.

  • Flutter앱에서 ImagePicker로 촬영한 사진이 Firebase Storage에 올라간 것을 볼 수 있습니다.
반응형
Comments