웹에서 Cloud Storage로 파일 업로드

Firebase용 Cloud Storage를 사용하면 Firebase에서 제공하고 관리하는 Cloud Storage 버킷에 파일을 빠르고 손쉽게 업로드할 수 있습니다.

파일 업로드

Cloud Storage에 파일을 업로드하려면 우선 파일 이름을 포함하여 파일의 전체 경로를 가리키는 참조를 만듭니다.

웹 모듈식 API

import { getStorage, ref } from "firebase/storage";

// Create a root reference
const storage = getStorage();

// Create a reference to 'mountains.jpg'
const mountainsRef = ref(storage, 'mountains.jpg');

// Create a reference to 'images/mountains.jpg'
const mountainImagesRef = ref(storage, 'images/mountains.jpg');

// While the file names are the same, the references point to different files
mountainsRef.name === mountainImagesRef.name;           // true
mountainsRef.fullPath === mountainImagesRef.fullPath;   // false 

웹 네임스페이스화된 API

// Create a root reference
var storageRef = firebase.storage().ref();

// Create a reference to 'mountains.jpg'
var mountainsRef = storageRef.child('mountains.jpg');

// Create a reference to 'images/mountains.jpg'
var mountainImagesRef = storageRef.child('images/mountains.jpg');

// While the file names are the same, the references point to different files
mountainsRef.name === mountainImagesRef.name;           // true
mountainsRef.fullPath === mountainImagesRef.fullPath;   // false 

Blob 또는 File에서 업로드

적절한 참조를 만들었으면 uploadBytes() 메서드를 호출합니다. uploadBytes()는 JavaScript FileBlob API를 통해 파일을 가져와서 Cloud Storage에 업로드합니다.

웹 모듈식 API

import { getStorage, ref, uploadBytes } from "firebase/storage";

const storage = getStorage();
const storageRef = ref(storage, 'some-child');

// 'file' comes from the Blob or File API
uploadBytes(storageRef, file).then((snapshot) => {
  console.log('Uploaded a blob or file!');
});

웹 네임스페이스화된 API

// 'file' comes from the Blob or File API
ref.put(file).then((snapshot) => {
  console.log('Uploaded a blob or file!');
});

바이트 배열에서 업로드

uploadBytes()FileBlob 유형 외에도 Uint8Array를 Cloud Storage에 업로드할 수 있습니다.

웹 모듈식 API

import { getStorage, ref, uploadBytes } from "firebase/storage";

const storage = getStorage();
const storageRef = ref(storage, 'some-child');

const bytes = new Uint8Array([0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x2c, 0x20, 0x77, 0x6f, 0x72, 0x6c, 0x64, 0x21]);
uploadBytes(storageRef, bytes).then((snapshot) => {
  console.log('Uploaded an array!');
});

웹 네임스페이스화된 API

var bytes = new Uint8Array([0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x2c, 0x20, 0x77, 0x6f, 0x72, 0x6c, 0x64, 0x21]);
ref.put(bytes).then((snapshot) => {
  console.log('Uploaded an array!');
});

문자열에서 업로드

Blob, File 또는 Uint8Array를 사용할 수 없으면 uploadString() 메서드를 사용하여 원시 문자열, base64, base64url 또는 data_url로 인코딩된 문자열을 Cloud Storage에 업로드할 수 있습니다.

웹 모듈식 API

import { getStorage, ref, uploadString } from "firebase/storage";

const storage = getStorage();
const storageRef = ref(storage, 'some-child');

// Raw string is the default if no format is provided
const message = 'This is my message.';
uploadString(storageRef, message).then((snapshot) => {
  console.log('Uploaded a raw string!');
});

// Base64 formatted string
const message2 = '5b6p5Y+344GX44G+44GX44Gf77yB44GK44KB44Gn44Go44GG77yB';
uploadString(storageRef, message2, 'base64').then((snapshot) => {
  console.log('Uploaded a base64 string!');
});

// Base64url formatted string
const message3 = '5b6p5Y-344GX44G-44GX44Gf77yB44GK44KB44Gn44Go44GG77yB';
uploadString(storageRef, message3, 'base64url').then((snapshot) => {
  console.log('Uploaded a base64url string!');
});

// Data URL string
const message4 = 'data:text/plain;base64,5b6p5Y+344GX44G+44GX44Gf77yB44GK44KB44Gn44Go44GG77yB';
uploadString(storageRef, message4, 'data_url').then((snapshot) => {
  console.log('Uploaded a data_url string!');
});

웹 네임스페이스화된 API

// Raw string is the default if no format is provided
var message = 'This is my message.';
ref.putString(message).then((snapshot) => {
  console.log('Uploaded a raw string!');
});

// Base64 formatted string
var message = '5b6p5Y+344GX44G+44GX44Gf77yB44GK44KB44Gn44Go44GG77yB';
ref.putString(message, 'base64').then((snapshot) => {
  console.log('Uploaded a base64 string!');
});

// Base64url formatted string
var message = '5b6p5Y-344GX44G-44GX44Gf77yB44GK44KB44Gn44Go44GG77yB';
ref.putString(message, 'base64url').then((snapshot) => {
  console.log('Uploaded a base64url string!');
});

// Data URL string
var message = 'data:text/plain;base64,5b6p5Y+344GX44G+44GX44Gf77yB44GK44KB44Gn44Go44GG77yB';
ref.putString(message, 'data_url').then((snapshot) => {
  console.log('Uploaded a data_url string!');
});

참조는 파일의 전체 경로를 정의하므로 비어 있지 않은 경로로 업로드해야 합니다.

파일 메타데이터 추가

파일을 업로드할 때 파일의 메타데이터를 지정할 수도 있습니다. 이 메타데이터는 name, size, contentType(통칭 MIME 유형) 등 일반적인 파일 메타데이터 속성을 포함합니다. Cloud Storage는 파일이 디스크에 저장된 경우 파일 확장자에서 콘텐츠 유형을 자동으로 유추하지만 메타데이터에 contentType이 지정된 경우에는 자동 감지된 유형을 재정의합니다. contentType 메타데이터가 지정되어 있지 않고 파일에 파일 확장자가 없는 경우 Cloud Storage는 기본적으로 application/octet-stream 유형을 지정합니다. 파일 메타데이터에 대한 자세한 내용은 파일 메타데이터 사용 섹션을 참조하세요.

웹 모듈식 API

import { getStorage, ref, uploadBytes } from "firebase/storage";

const storage = getStorage();
const storageRef = ref(storage, 'images/mountains.jpg');

// Create file metadata including the content type
/** @type {any} */
const metadata = {
  contentType: 'image/jpeg',
};

// Upload the file and metadata
const uploadTask = uploadBytes(storageRef, file, metadata);

웹 네임스페이스화된 API

// Create file metadata including the content type
var metadata = {
  contentType: 'image/jpeg',
};

// Upload the file and metadata
var uploadTask = storageRef.child('images/mountains.jpg').put(file, metadata);

업로드 관리

업로드 시작 외에도 pause(), resume(), cancel() 메서드를 사용하여 업로드를 일시중지, 재개, 취소할 수 있습니다. pause() 또는 resume()을 호출하면 pause 또는 running으로 상태가 변경됩니다. cancel() 메서드를 호출하면 업로드가 실패하고 업로드가 취소되었음을 나타내는 오류가 반환됩니다.

웹 모듈식 API

import { getStorage, ref, uploadBytesResumable } from "firebase/storage";

const storage = getStorage();
const storageRef = ref(storage, 'images/mountains.jpg');

// Upload the file and metadata
const uploadTask = uploadBytesResumable(storageRef, file);

// Pause the upload
uploadTask.pause();

// Resume the upload
uploadTask.resume();

// Cancel the upload
uploadTask.cancel();

웹 네임스페이스화된 API

// Upload the file and metadata
var uploadTask = storageRef.child('images/mountains.jpg').put(file);

// Pause the upload
uploadTask.pause();

// Resume the upload
uploadTask.resume();

// Cancel the upload
uploadTask.cancel();

업로드 진행률 모니터링

업로드 중에 업로드 작업으로 인해 state_changed 관찰자에서 다음과 같은 진행 이벤트가 발생할 수 있습니다.

이벤트 유형 일반적인 용도
running 이 이벤트는 업로드가 시작되거나 재개될 때 발생하며 일반적으로 pause 이벤트와 함께 사용됩니다. 업로드 규모가 보다 큰 경우 진행 상황이 업데이트됨에 따라 이 이벤트가 여러 번 발생할 수 있습니다.
pause 이 이벤트는 업로드가 일시중지될 때마다 발생하며 일반적으로 running 이벤트와 함께 사용됩니다.

이벤트가 발생하면 TaskSnapshot 객체가 다시 전달됩니다. 이 스냅샷은 이벤트 발생 시점의 작업 상태로서 변경이 불가능합니다. 이 객체는 다음과 같은 속성을 포함합니다.

속성 유형 설명
bytesTransferred Number 이 스냅샷을 생성한 시점까지 전송된 총 바이트 수입니다.
totalBytes Number 업로드가 예정된 총 바이트 수입니다.
state firebase.storage.TaskState 업로드의 현재 상태입니다.
metadata firebaseStorage.Metadata 업로드가 완료되기 전에는 서버에 전송된 메타데이터입니다. 업로드가 완료된 후에는 서버에서 다시 전송한 메타데이터입니다.
task firebaseStorage.UploadTask 스냅샷 대상 작업으로서 작업을 일시중지, 재개 또는 취소하는 데 사용할 수 있습니다.
ref firebaseStorage.Reference 이 작업이 유래된 참조입니다.

이러한 상태 변화와 TaskSnapshot의 속성을 결합하면 업로드 이벤트를 간편하고 효과적인 방법으로 모니터링할 수 있습니다.

웹 모듈식 API

import { getStorage, ref, uploadBytesResumable, getDownloadURL } from "firebase/storage";

const storage = getStorage();
const storageRef = ref(storage, 'images/rivers.jpg');

const uploadTask = uploadBytesResumable(storageRef, file);

// Register three observers:
// 1. 'state_changed' observer, called any time the state changes
// 2. Error observer, called on failure
// 3. Completion observer, called on successful completion
uploadTask.on('state_changed', 
  (snapshot) => {
    // Observe state change events such as progress, pause, and resume
    // Get task progress, including the number of bytes uploaded and the total number of bytes to be uploaded
    const progress = (snapshot.bytesTransferred / snapshot.totalBytes) * 100;
    console.log('Upload is ' + progress + '% done');
    switch (snapshot.state) {
      case 'paused':
        console.log('Upload is paused');
        break;
      case 'running':
        console.log('Upload is running');
        break;
    }
  }, 
  (error) => {
    // Handle unsuccessful uploads
  }, 
  () => {
    // Handle successful uploads on complete
    // For instance, get the download URL: https://firebasestorage.googleapis.com/...
    getDownloadURL(uploadTask.snapshot.ref).then((downloadURL) => {
      console.log('File available at', downloadURL);
    });
  }
);

웹 네임스페이스화된 API

var uploadTask = storageRef.child('images/rivers.jpg').put(file);

// Register three observers:
// 1. 'state_changed' observer, called any time the state changes
// 2. Error observer, called on failure
// 3. Completion observer, called on successful completion
uploadTask.on('state_changed', 
  (snapshot) => {
    // Observe state change events such as progress, pause, and resume
    // Get task progress, including the number of bytes uploaded and the total number of bytes to be uploaded
    var progress = (snapshot.bytesTransferred / snapshot.totalBytes) * 100;
    console.log('Upload is ' + progress + '% done');
    switch (snapshot.state) {
      case firebase.storage.TaskState.PAUSED: // or 'paused'
        console.log('Upload is paused');
        break;
      case firebase.storage.TaskState.RUNNING: // or 'running'
        console.log('Upload is running');
        break;
    }
  }, 
  (error) => {
    // Handle unsuccessful uploads
  }, 
  () => {
    // Handle successful uploads on complete
    // For instance, get the download URL: https://firebasestorage.googleapis.com/...
    uploadTask.snapshot.ref.getDownloadURL().then((downloadURL) => {
      console.log('File available at', downloadURL);
    });
  }
);

오류 처리

업로드 시 오류가 발생하는 이유는 로컬 파일이 없는 경우, 사용자에게 원하는 파일을 업로드할 권한이 없는 경우 등 다양합니다. 오류에 대한 자세한 내용은 문서의 오류 처리 섹션을 참조하세요.

전체 예시

다음은 진행률 모니터링 및 오류 처리를 포함하는 업로드를 보여주는 전체 예시입니다.

웹 모듈식 API

import { getStorage, ref, uploadBytesResumable, getDownloadURL } from "firebase/storage";

const storage = getStorage();

// Create the file metadata
/** @type {any} */
const metadata = {
  contentType: 'image/jpeg'
};

// Upload file and metadata to the object 'images/mountains.jpg'
const storageRef = ref(storage, 'images/' + file.name);
const uploadTask = uploadBytesResumable(storageRef, file, metadata);

// Listen for state changes, errors, and completion of the upload.
uploadTask.on('state_changed',
  (snapshot) => {
    // Get task progress, including the number of bytes uploaded and the total number of bytes to be uploaded
    const progress = (snapshot.bytesTransferred / snapshot.totalBytes) * 100;
    console.log('Upload is ' + progress + '% done');
    switch (snapshot.state) {
      case 'paused':
        console.log('Upload is paused');
        break;
      case 'running':
        console.log('Upload is running');
        break;
    }
  }, 
  (error) => {
    // A full list of error codes is available at
    // https://firebase.google.com/docs/storage/web/handle-errors
    switch (error.code) {
      case 'storage/unauthorized':
        // User doesn't have permission to access the object
        break;
      case 'storage/canceled':
        // User canceled the upload
        break;

      // ...

      case 'storage/unknown':
        // Unknown error occurred, inspect error.serverResponse
        break;
    }
  }, 
  () => {
    // Upload completed successfully, now we can get the download URL
    getDownloadURL(uploadTask.snapshot.ref).then((downloadURL) => {
      console.log('File available at', downloadURL);
    });
  }
);

웹 네임스페이스화된 API

// Create the file metadata
var metadata = {
  contentType: 'image/jpeg'
};

// Upload file and metadata to the object 'images/mountains.jpg'
var uploadTask = storageRef.child('images/' + file.name).put(file, metadata);

// Listen for state changes, errors, and completion of the upload.
uploadTask.on(firebase.storage.TaskEvent.STATE_CHANGED, // or 'state_changed'
  (snapshot) => {
    // Get task progress, including the number of bytes uploaded and the total number of bytes to be uploaded
    var progress = (snapshot.bytesTransferred / snapshot.totalBytes) * 100;
    console.log('Upload is ' + progress + '% done');
    switch (snapshot.state) {
      case firebase.storage.TaskState.PAUSED: // or 'paused'
        console.log('Upload is paused');
        break;
      case firebase.storage.TaskState.RUNNING: // or 'running'
        console.log('Upload is running');
        break;
    }
  }, 
  (error) => {
    // A full list of error codes is available at
    // https://firebase.google.com/docs/storage/web/handle-errors
    switch (error.code) {
      case 'storage/unauthorized':
        // User doesn't have permission to access the object
        break;
      case 'storage/canceled':
        // User canceled the upload
        break;

      // ...

      case 'storage/unknown':
        // Unknown error occurred, inspect error.serverResponse
        break;
    }
  }, 
  () => {
    // Upload completed successfully, now we can get the download URL
    uploadTask.snapshot.ref.getDownloadURL().then((downloadURL) => {
      console.log('File available at', downloadURL);
    });
  }
);

이제 파일 업로드가 끝났으므로 Cloud Storage에서 다운로드하는 방법을 알아보세요.