본문 바로가기

프론트엔드

Firebase storage로 첨부파일 다운로드 구현하기

  • 프로젝트: 공우 홈페이지
  • 키워드: firebae storage, download file in javascript, attachment
  • 상황
    1. 공우 지원 방법 section에서 첨부파일 다운로드 기능을 구현해야한다.

      지원 방법 디자인
    2. 파일들은 firebase storage '/example' 폴더 하위에 저장되어있다.
  • 해결 방법
    1. Attachment Component는 이름과 파일명을 prop으로 받는다.
        export interface Props {
        title: string;  // ex> 파일이름.docx
        filename: string; // ex> example/file.docx
      }
      
      const Attachment: React.FC<Props> = ({ title, filename }) => {
        ...
      }


    2. 최초로 버튼을 누르면 setUrlFromStorageAndDownloadFile 함수를 통해 firebase storage 첨부파일에 대한 url을 받아온다.
        const setUrlFromStorageAndDownloadFile = useCallback(() => {
        storage
          .ref()
          .child(filename)
          .getDownloadURL()
          .then((storageUrl) => {
            setUrl(storageUrl);
            downloadFile(storageUrl);
          })
          .catch((e) => e);
      }, [storage, filename, downloadFile]);


    3. 그 후, downloadFile 함수에서 실제로 파일을 다운로드 한다.
        const downloadFile = useCallback((url) => {
        const link = document.createElement('a');
        document.body.appendChild(link);
        link.href = url;
        link.click();
        link.remove();
      }, []);


    4. Attachment 전체 소스코드이다. 처음 버튼을 누르면(onClick) setUrl로 url을 저장한 뒤 downloadFile 함수를 호출하고, 버튼을 한 번 더 누르면 저장하고 있던 url로 바로 downloadFile 함수를 호출한다.
        import React, { useCallback, useState } from 'react';
      import * as S from '.../styles';
      import Image from 'next/image';
      import Download from '.../download.svg';
      import { useFirebaseStorage } from '.../firebase';
      
      export interface Props {
        title: string;
        filename: string;
      }
      
      const Attachment: React.FC<Props> = ({ title, filename }) => {
        const storage = useFirebaseStorage();
        const [url, setUrl] = useState('');
      
        const downloadFile = useCallback((url) => {
          const link = document.createElement('a');
          document.body.appendChild(link);
          link.href = url;
          link.click();
          link.remove();
        }, []);
      
        const setUrlFromStorageAndDownloadFile = useCallback(() => {
          storage
            .ref()
            .child(filename)
            .getDownloadURL()
            .then((storageUrl) => {
              setUrl(storageUrl);
              downloadFile(storageUrl);
            })
            .catch((e) => e);
        }, [storage, filename, downloadFile]);
      
        return (
          <S.Wrapper onClick={() => (url ? downloadFile(url) : setUrlFromStorageAndDownloadFile())}>
            <Image src={Download} alt="" />
            <p>{title}</p>
          </S.Wrapper>
        );
      };
      
      export default Attachment;


    5. 이제 지원 방법 section에서 Attachment 컴포넌트를 불러오면 된다!
        <Attachment
        title="2021 STEM 12.5th recruitment application form.docx"
        filename="example/2021_stem_application.docx"
      />
      <Attachment
        title="2021 STEM 12.5th recruitment application form.hwp"
        filename="example/2021_stem_application.hwp"
      />