image 업로드 (file 객체)

HYOJIN·2021년 10월 4일
0

React

목록 보기
6/9
post-thumbnail

firebase Storage

이미지와 같은 파일을 저장하는 클라우드 저장소

Rules

  • write: if request.auth != null;

    • 인증된 사용자(로그인 한 사용자)에게 쓰기 권한 부여

image 업로드

firebase.js

import

  • storage 서비스 사용
import 'firebase/storage';

export

const storage = firebase.storage();

export {auth, apiKey, firestore, storage};

Upload.js

파일 선택

  • ref를 사용하여 input에 접근
const Upload = (props) =>{
    const fileInput = React.useRef();

    const selectFile = (e) =>{
        console.log(e.target.files[0]);
        // 위 아래 콘솔이 같은 값
        console.log(fileInput.current.files[0]);
    }

    return(
        <React.Fragment>
            <input type='file' onChange={selectFile}  ref={fileInput}/>
        </React.Fragment>
    )
}

import

import {storage} from './firebase'

버튼을 눌러 storage에 업로드

  • 파일 업로드 - firebase docs 참고

  • 파일 이름을 포함한 ref 참조를 만들기

 const uploadFB = () =>{
        let image = fileInput.current.files[0];
              // storage에서 만든 폴더(images)
        const _upload = storage.ref(`images/${image.name}`).put(image);

        // 무엇을 업로드 했는지 확인
        _upload.then((snapshot) =>{
            console.log(snapshot);
        })
    }

image 링크 받아오기

_upload.then((snapshot) =>{
      console.log(snapshot);

      snapshot.ref.getDownloadURL().then((url) =>{
      console.log(url)
  })
})
  • 링크는 Upload 컴포넌트만 가지고 있음
  • redux로 빼서 PostWrite 컴포넌트도 알고 있게 해야함
  • 업로드 후 링크가 redux에 남아있게 만들어야함

image 모듈 생성

image.js

import

import {createAction, handleActions} from 'redux-actions';
import {produce} from 'immer';

import {storage} from '../../shared/firebase';

action

// 업로드 중인지 아닌지 알게해주는 액션
const UPLOADING = 'UPLOADING';
// 실제로 파일 업로드 하는 액션
const UPLOAD_IMAGE = 'UPLOAD_IMAGE';

action creators

const uploading = createAction(UPLOADING, (uploading) => ({uploading}));
const uploadImage = createAction(UPLOAD_IMAGE, (image_url)=>({image_url}));

initialState

const initialState = {
    image_url:'',
    uploading: false,
}

middleware

const uploadImageFB = (image) =>{


    return function(dispatch, getState, {history}){
        //  업로드 시작하기 전에
        dispatch(uploading(true))

        const _upload = storage.ref(`images/${image.name}`).put(image);

        // 무엇을 업로드 했는지 확인
        _upload.then((snapshot) =>{
            console.log(snapshot);

            // stroage에 올린 이미지 링크 받아오기
            snapshot.ref.getDownloadURL().then((url) =>{
                console.log(url)
                // 업로드 이미지 기록
                dispatch(uploadImage(url))
            });
        }).catch(err =>{
            dispatch(uploading(false));
        })
    }
}

reducer

export default handleActions({
    [UPLOAD_IMAGE]: (state, action) => produce(state, (draft) =>{
        // image url 고치기
        draft.image_url = action.payload.image_url;
        draft.uploading = false;
    }),
    [UPLOADING] : (state, action) => produce(state, (draft) =>{
        // 업로딩 상태 바꾸기
        draft.uploading = action.payload.uploading;
    })
}, initialState);

export

const actionCreators = {
    uploadImage,
    uploadImageFB,
}

export {actionCreators}

configureStore.js

import

import Image from './modules/image';

rootreducer

const rootReducer = combineReducers({
  user: User,
  post: Post, 
  image: Image,

  router: connectRouter(history),
});

Upload.js

import

import {useDispatch, useSelector} from 'react-redux';
import { actionCreators as imageActions } from "../redux/modules/image";

uploading 되는 동안 버튼 안눌리게

const is_uploading = useSelector(state => state.image.uploading);

uploadImageFB 호출

  • 파일이 없을 시 경고창 생성
 const uploadFB = () =>{
 
    if(!fileInput.current || fileInput.current.files.length === 0){
        window.alert('파일 선택');
        return;
    }
    dispatch(imageActions.uploadImageFB(fileInput.current.files[0]))
}

uploading 상태에 따라 파일 선택 막기

  • disabled가 true이면 파일 선택 버튼 비활성화
<input type='file' onChange={selectFile}  ref={fileInput} disabled={is_uploading} />
profile
https://github.com/hyojin-k

0개의 댓글