본문 바로가기

Flutter/12 Clone 'Used Goods app'

[Flutter] Clone - 당근마켓34(InputScreen - image uploading)

이번에는 image picker 에서 선택한 이미지를 Firebase Storage 에 저장하고 저장위치를 알아내는 부분을 구현해보겠습니다.

개발환경 : 윈도우11, 안드로이드 스튜디오, flutter 3.0.1

 

 

 

필요한 패키지는 아래와 같습니다.

 

firebase_storage: ^10.3.5

 

 

 

패키지를 추가하고 Storage 의 Rules 부분을 수정해야 한다. 수정하지 않으면 데이터를 업로드 할 수 없다.

 

rules_version = '2';
service firebase.storage {
  match /b/{bucket}/o {
    match /{allPaths=**} {
      allow read, write: if request.auth != null;
    }
  }
}

 

 

 

./src/models/item_model.dart - 업로드할때 중복되지 않게 키값을 조항하는 함수 추가

 

static String generateItemKey(String uid) {
  String timeInMilli = DateTime.now().millisecondsSinceEpoch.toString();

  return '${uid}_$timeInMilli';
}

 

 

 

./src/repo/image_storage.dart 신규생성

 

import 'dart:typed_data';
import 'package:firebase_storage/firebase_storage.dart';

import '../utils/logger.dart';

class ImageStorage {

  static Future<List<String>> uploadImage(List<Uint8List> images, String itemKey) async {

    // 이미지 타입지정,
    var metaData = SettableMetadata(contentType: 'image/jpeg');
    List<String> downloadUrls = [];

    for (var i = 0; i < images.length; i++) {
      // 저장위치 설정 ref('images/$itemKey/$i.jpg')
      // 참고자료 - "https://firebase.google.com/docs/storage/android/create-reference?authuser=0"
      Reference ref =
      FirebaseStorage.instance.ref('images/$itemKey/$i.jpg');
      if (images.isNotEmpty) {
        // 데이터 업로드,
        await ref.putData(images[i], metaData).catchError((onError){
          logger.e('picture uploading error: ' + onError.toString());
        });
        // 업로드 완료된 파일 위치 저장,
        downloadUrls.add(await ref.getDownloadURL());
      }
    }

    return downloadUrls;
  }
}

 

 

 

./src/screens/input/input_screen.dart

 

// 이미지 업로딩 및 다운로드주소 저장
void attemptCreateItem() async {
  if (FirebaseAuth.instance.currentUser == null) return;
  // 완료 버튼 클릭
  isCreatingItem = true;
  // setState 해줘야 인디케이터가 동작한다,
  setState(() {});

  final String userKey = FirebaseAuth.instance.currentUser!.uid;
  final String userPhone = FirebaseAuth.instance.currentUser!.phoneNumber!;
  final String itemKey = ItemModel2.generateItemKey(userKey);
  List<Uint8List> images = SelectImageController.to.images;
  // uploading raw data and return the Urls,
  List<String> downloadUrls = await ImageStorage.uploadImage(images, itemKey);
  final num? price = num.tryParse(_priceController.text.replaceAll(RegExp(r'\D'), ''));

  logger.d('upload finished(${downloadUrls.length}) : $downloadUrls');

  Get.back();
}


// AppBar 에 옵션 추가, 이미지 저장동안 인디케이터 처리
bottom: PreferredSize(
  preferredSize: Size(_size.width, 3),
  child: isCreatingItem ? const LinearProgressIndicator(minHeight: 3) : Container(),
),