±âŸ(framework)
2018.03.21 / 01:54

Firebase Web äÆÃ¾Û ¸¸µé±â - Storage¸¦ ÀÌ¿ëÇÑ ÆÄÀÏ Àü¼Û±â´É

ÈÞ°í
Ãßõ ¼ö 196
´Ü¼ø äÆø޼¼Áö¸¦ ³Ñ¾î ÆÄÀÏÀ» ¼­·Î ÁÖ°í ¹ÞÀ» ¼ö ÀÖ´Â ±â´ÉÀ» ±¸ÇöÇغ¸°Ú½À´Ï´Ù. Firebase Storage¸¦ È°¿ëÇÏ°Ô µË´Ï´Ù  Å¬¸³¹öÆ°À» ´©¸£¸é ÆÄÀÏÀ» ¼±ÅÃÀ» ÇÒ ¼ö ÀÖ°í, ÆÄÀÏÀ» ¼±ÅÃÇϸé, Æ˾÷ ¸ð´Þ âÀÌ ¶ß¸é¼­  ÆÄÀÏ Àü¼Û ÇöȲÀ» º¼ ¼ö ÀÖ´Â ÇÁ·Î±×·¹½º¹Ù°¡ ¿òÁ÷À̸ç, ÃÖÁ¾ÀûÀ¸·Î ÆÄÀÏÀ» ´Ù¿î·Îµå ¹ÞÀ» ¼ö ÀÖ´Â ¸µÅ©Á¤º¸°¡ ¸Þ¼¼Áö·Î Àü´Þ µË´Ï´Ù.

  



Äڵ带 ½ÃÀÛÇϱâ Àü Firebase console ·Î µé¾î°¡¼­ Storage ¸Þ´º·Î µé¾î°©´Ï´Ù.  Ã³À½ µé¾î°¡¸é ¾Æ·¡¿Í °°Àº È­¸éÀÌ ³ª¿É´Ï´Ù. ½ÃÀÛÇϱ⠹öÆ°À» ´­·¯  ÁÖ¼¼¿ä. ½ÃÀÛÇϱ⠹öÆ°À» ´­·¯¾ß ±âº»ÀûÀÎ ±ÇÇÑÀÌ »ý¼ºÀÌ µÇ°í BucketÀÌ »ý¼ºÀÌ µÇ¸ç Storage¸¦ »ç¿ëÇÒ ¼ö ÀÖ´Â »óÅ°¡ µË´Ï´Ù.


ÀÌÁ¦ Äڵ带 ÀÛ¼ºÇغ¸°Ú½À´Ï´Ù. ¾Æ·¡ÀÇ Äڵ带 Ãß°¡ÇØÁֽʽÿÀ.

<script>
/**
* Ãʱâ ÇÊµå º¯¼ö ÇÒ´ç
*/
FirebaseChat.prototype.init = function(){
//...»ý·«
this.iBtnAttach = document.getElementById('iBtnAttach');
this.attachFile = document.getElementById('attachFile');
}
/**
* Ãʱâ À̺¥Æ® ¹ÙÀεù
*/
FirebaseChat.prototype.initEvent = function(){
//...»ý·«
this.iBtnAttach.addEventListener('click', this.onBtnAttachClick.bind(this));
this.attachFile.addEventListener('change', this.onAttachFile.bind(this));
}
/**
* ÷ºÎÆÄÀÏ ¹öÆ° Ŭ¸¯
*/
FirebaseChat.prototype.onBtnAttachClick = function(){
this.attachFile.click();
}
/**
* ÷ºÎÆÄÀÏ Àü¼Û
*/
FirebaseChat.prototype.onAttachFile = function(event){
$('#dnModal').modal('open');
var files = event.target.files;
var filesLength = files.length;
var progressBar = document.getElementById('dvProgressBar');
var fileName = files[0].name;
var path = FirebaseChat.yyyyMMddHHmmsss().substr(0, 8) +'/'+this.roomId + '/' + this.auth.currentUser.uid + '/' + fileName;
var uploadTask = firebase.storage().ref().child(path).put(files[0]);
var cbProgress = function(snapshot){ // ÁøÇà °úÁ¤
var progress = (snapshot.bytesTransferred / snapshot.totalBytes) * 100;
progressBar.style.width = progress+'%';
}
var cbError = function(error) { // ¿¡·¯¹ß»ý
console.log(error);
$('#dnModal').modal('close');
alert('¾÷·Îµå Áß ¿¡·¯°¡ ¹ß»ýÇÏ¿´½À´Ï´Ù.');
}
var cbComplete = function() { // ¿Ï·á
//ÇÁ·Î±×·¹½º¹Ù ´Ý±â
$('#dnModal').modal('close');
//¿Ï·á ´Ù¿î·Îµå ¸µÅ© ¸Þ¼¼Áö º¸³»±â
this.saveMessages(null, uploadTask.snapshot.downloadURL, fileName);
//files ¸®¼Â
event.target.value='';
}
//ÇÁ·Î±×·¹½º¹Ù
uploadTask.on('state_changed', cbProgress.bind(this) , cbError.bind(this), cbComplete.bind(this));
}
/**
* ¸Þ¼¼Áö Àü¼Û
*/
FirebaseChat.prototype.saveMessages = function(inviteMessage, downloadURL, fileName){
var user = this.auth.currentUser;
var msg = this.dvInputChat.innerHTML.trim();
//ÃÊ´ë¸Þ¼¼Áö
if(inviteMessage && inviteMessage.length > 0){
msg = inviteMessage;
}
//ÆÄÀÏÀü¼Û ¸Þ¼¼Áö
if(downloadURL && fileName){
msg = "<a class='waves-effect waves-light btn blue' download='"+fileName+"' href='"+ downloadURL +"'>´Ù¿î·Îµå</a></br><span class=''>ÆÄÀϸí : "+ fileName +"</span>";
}
if(msg.length > 0){
this.dvInputChat.focus();
this.dvInputChat.innerHTML = '';
var multiUpdates = {};
var messageRefKey = this.messageRef.push().key; // ¸Þ¼¼Áö Å°°ª ±¸Çϱâ
var convertMsg = downloadURL ? msg : FirebaseChat.convertMsg(msg); //´Ù¿î·Îµå URLÀÏ °æ¿ì convertÇÏÁö ¾ÊÀ½
//...»ý·«
//À¯Àúº° ·ë¸®½ºÆ® ÀúÀå
var roomUserListLength = this.roomUserlist.length;
if(this.roomUserlist && roomUserListLength > 0){
for(var i = 0; i < roomUserListLength ; i++){
multiUpdates['UserRooms/'+ this.roomUserlist[i] +'/'+ this.roomId] = {
roomId : this.roomId,
roomUserName : this.roomUserName.join(this.SPLIT_CHAR),
roomUserlist : this.roomUserlist.join(this.SPLIT_CHAR),
roomType : roomUserListLength > 2 ? this.MULTI : this.ONE_VS_ONE,
roomOneVSOneTarget : roomUserListLength == 2 && i == 0 ? this.roomUserlist[1] : // 1´ë 1 ´ëÈ­ÀÌ°í i °ªÀÌ 0 À̸é
roomUserListLength == 2 && i == 1 ? this.roomUserlist[0] // 1´ë 1 ´ëÈ­ ÀÌ°í i°ªÀÌ 1À̸é
: '', // ³ª¸ÓÁö
lastMessage : downloadURL ? '´Ù¿î·Îµå' : convertMsg,
profileImg : user.photoURL ? user.photoURL : '',
timestamp: firebase.database.ServerValue.TIMESTAMP
};
}
}
this.database.ref().update(multiUpdates);
}
}
view rawindex.html hosted with ❤ by GitHub




À§ ÄÚµå´Â äÆùæ È­¸é¿¡¼­ Ŭ¸³¸ð¾çÀÇ ¾ÆÀÌÄÜÀ» Ŭ¸¯ Çϸé file ŸÀÔÀÇ input ű׸¦ Ŭ¸¯ÇÏ°Ô µÇ°í, ÆÄÀÏÀÌ ¼±ÅõǾîÁö¸é onAttachFile ¸Þ¼Òµå°¡ ½ÇÇàµË´Ï´Ù. 

 ÆÄÀÏ Ã·ºÎ ¸Þ¼¼Áö¸¦ º¸³»´Â ÇÙ½É ¸Þ¼ÒµåÀΠ onAttachFile ¸Þ¼Òµå¿¡ ´ëÇؼ­ Á¶±Ý ´õ ÀÚ»çÇÏ°Ô »ìÆ캸°Ú½À´Ï´Ù.

 ¸Þ¼ÒµåÀÇ ½ÃÀÛÄÚµå´Â ÆÄÀÏ ´Ù¿î·Îµå Æ˾÷À» ¶ç¿ì°Ô µÇ¾î ÀÖ½À´Ï´Ù.


¼±ÅÃÇÑ ÆÄÀÏÀº event.target.files ¿¡ µ¥ÀÌÅÍ°¡ µé¾î¿É´Ï´Ù. ÆÄÀÏÀ» Çϳª ¼±ÅÃÇÒ »ÓÀÌÁö¸¸ ÇüÅ´ fileList °´Ã¼·Î µ¥ÀÌÅÍ°¡ µé¾î¿É´Ï´Ù. ±×·¸±â¶§¹®¿¡ ¹è¿­Ã³·³ ù¹ø° À妽ºÀÇ ÆÄÀÏÀ» ¼±ÅÃÇÏ¿© ÆÄÀÏ¸í º¯¼ö¿¡ ÇÒ´çÇÕ´Ï´Ù.

var files = event.target.files;
var fileName files[0].name;

ÆÄÀÏÀ» ÀúÀåÇÏ´Â À§Ä¡´Â '/³¯Â¥(yyyyMMdd)/¹æID/À¯ÀúUID/ÆÄÀϸí' ÇüÅ·ΠµÇ¾î ÀÖ½À´Ï´Ù. ÆÄÀÏ ÀúÀå °æ·Î Áß¿¡ ³¯Â¥¸¦ µÐ°ÍÀº Firebase Functions ±â´ÉÀ» ÅëÇؼ­ ÁÖ±âÀûÀ¸·Î »èÁ¦¸¦ ½Ç½ÃÇϱâ À§ÇÔÀÔ´Ï´Ù. ¿¹Á¦ ÈĹݺο¡¼­ ´Ù·ç¾îº¼ °èȹÀÔ´Ï´Ù.

var path = FirebaseChat.yyyyMMddHHmmsss().substr(0, 8'/'+this.roomId + '/' + this.auth.currentUser.uid + '/' + fileName;
¾Æ·¡Äڵ尡 ½ÇÁúÀûÀ¸·Î ÆÄÀÏÀ» ÀúÀåÇÏ´Â ÄÚµåÀÔ´Ï´Ù. ¾Æ·¡ÀÇ ÄÚµå Áß ref¸Þ¼Òµå´Â Realtime Database¿Í ºñ½ÁÇÏ°Ô ÀúÀåµÇ´Â °æ·Î¸¦ ÀÇ¹Ì ÇÕ´Ï´Ù. ½ÇÁúÀûÀÎ ÀúÀåÀº Google Cloud Storage¿¡ ÀúÀåÀÌ µË´Ï´Ù.

ÀúÀåÇÏ´Â put ¸Þ¼Òµå´Â UploadTask °´Ã¼¸¦ ¹Ýȯ ÇÕ´Ï´Ù. UploadTask °´Ã¼·Î ¾÷·Îµå °ü¸®¸¦ ¼öÇàÇÒ¼ö ÀÖ½À´Ï´Ù. 
var uploadTask = firebase.storage().ref().child(path).put(files[0]);

UploadTask°´Ã¼´Â 'state_changed' À̺¥Æ®¸¦ ¹ß»ý½Ãŵ´Ï´Ù. ¾Æ·¡ÀÇ ÄÚµå´Â 'state_changed' À̺¥Æ®¸¦ ¹Þ¾ÒÀ» ¶§ 3°¡ÁöÀÇ Äݹé ÇÔ¼ö¸¦ ÆĶó¹ÌÅÍ·Î ÁöÁ¤ÇÑ ÄÚµåÀÔ´Ï´Ù. ù¹ø° ÄݹéÇÔ¼ö´Â ÁøÇà Áß ¼öÇàÇÏ´Â ÇÔ¼öÀÌ°í, µÎ¹ø°´Â ¿¡·¯°¡ ¹ß»ýÇßÀ»¶§, ¼¼¹ø°´Â ¾÷·Îµå°¡ ¿Ï·á?çÀ? ¶§ ¼öÇàµË´Ï´Ù.
uploadTask.on('state_changed'cbProgress.bind(this) , cbError.bind(this), cbComplete.bind(this));
ÁøÇà Áß ¼öÇàÇÏ´Â Äݹé ÇÔ¼öÀÎ cbProgresss¸¦ »ìÆ캸¸é, ÇÁ·Î±×·¡½º¹ÙÀÇ °ÔÀÌÁöÀÇ ³ÐÀ̸¦ Á¶Á¤ÇÏ°Ô µË´Ï´Ù.

var cbProgress = function(snapshot){ // ÁøÇà °úÁ¤
    var progress = (snapshot.bytesTransferred / snapshot.totalBytes) * 100;
    progressBar.style.width = progress+'%';
}

¿¡·¯ ÄݹéÇÔ¼öÀÎ cbErrorÀ» »ìÆ캸¸é, »ç¿ëÀÚ¿¡°Ô ¿¡·¯°¡ ¹ß»ýÇÏ¿´À½À» alertâÀ¸·Î ¾Ë¸®°í, Äֿܼ¡ ¿¡·¯³»¿ëÀ» Ãâ·ÂÇÕ´Ï´Ù.
var cbError = function(error) { // ¿¡·¯¹ß»ý
    console.log(error);
    $('#dnModal').modal('close');
    alert('¾÷·Îµå Áß ¿¡·¯°¡ ¹ß»ýÇÏ¿´½À´Ï´Ù.');
}
¸¶Áö¸·À¸·Î ¿Ï·á Äݹé ÇÔ¼öÀÎ cbComplete ÇÔ¼ö¸¦ º¸¸é, Æ˾÷ ¸ð´ÞâÀ» ´Ý°í, ´Ù¿î·Îµå urlÁ¤º¸°¡ ´ã±ä ¸Þ¼¼Áö¸¦ äÆù濡 ¸Þ¼¼Áö¸¦ Àü¼ÛÇÏ°Ô µË´Ï´Ù.
var cbComplete = function() { // ¿Ï·á
    //ÇÁ·Î±×·¹½º¹Ù ´Ý±â
    $('#dnModal').modal('close');

    //¿Ï·á ´Ù¿î·Îµå ¸µÅ© ¸Þ¼¼Áö º¸³»±â
    this.saveMessages(null, uploadTask.snapshot.downloadURL, fileName);

    //files ¸®¼Â
    event.target.value='';
}



Firebase Storage´Â ¹«·áÀÇ °æ¿ì ÀúÀå¿ë·® 5GB,´Ù¿î·Îµå Å©±â ÇÏ·ç 1GB, ÇÏ·ç ¾÷·Îµå 20000ȸ, ´Ù¿î·Îµå 50000ȸÀÇ Á¦ÇÑÀÌ ÀÖ½À´Ï´Ù.  À¯·á Á¾·®Á¦ ¿ä±ÝÀÇ °æ¿ì ÀÌ·¯ÇÑ Á¦ÇÑÀº ¾øÁö¸¸, »ç¿ëÇÑ ¸¸Å­ ºñ¿ëÀÌ Ã»±¸µË´Ï´Ù. 

ÀÌ·¯ÇÑ ÀÌÀ¯·Î Storage´Â º¸¾È ¼³Á¤ÀÌ Áß¿äÇÕ´Ï´Ù. º¸¾È ¼³Á¤À» ÅëÇؼ­ Á¢±Ù ±ÇÇÑÀ̳ª ¾÷·Îµå ¿ë·®, ¾÷·Îµå °¡´ÉÇÑ ÆÄÀÏ Å¸ÀÔÀ» ÁöÁ¤ÇÒ ¼ö ÀÖ½À´Ï´Ù.

StorageÀÇ ±âº» º¸¾ÈÀº AuthenticationÀ» ÅëÇؼ­ ÀÎÁõ ¹ÞÀº »ç¶÷µé¿¡°Ô Àбâ¿Í ¾²±â ±ÇÇÑÀÌ ºÎ¿©µÇ¾î ÀÖ½À´Ï´Ù.
ÇÁ·ÎÁ§Æ®¿¡¼­ ±ÇÇÑ ÆÄÀÏÀÎ storage.rules ÆÄÀÏÀ» ¿­¾îº¸¼¼¿ä. ¾Æ·¡¿Í °°ÀÌ ÀÔ·ÂÀÌ µÇ¾î ÀÖ½À´Ï´Ù.

service firebase.storage {
match /b/{bucket}/o {
match /{allPaths=**} {
allow read, write: if request.auth!=null;
}
}
}
view rawstorage.rules hosted with ❤ by GitHub




¾Õ¼­ ÆÄÀÏÀ» ÀúÀåÇÒ ¶§ '/³¯Â¥(yyyyMMdd)/¹æID/À¯ÀúUID/ÆÄÀϸí' ÇüÅ·ΠÀúÀåÇÏ¿´½À´Ï´Ù. ÀÌÁ¦ Àбâ±ÇÇÑÀº ÀÎÁõ¹ÞÀº À¯Àú ¸ðµÎ¿¡°Ô ±ÇÇÑÀ» ºÎ¿©Çϳª ¾²±â ±ÇÇÑÀº º»ÀÎÀÇ À¯ÀúUID °æ·Î¿¡¸¸ Á¢±ÙÇؼ­ ÀúÀåÇÒ¼ö ÀÖµµ·Ï ÇÏ°Ú½À´Ï´Ù. ±×¸®°í À̹ÌÁö ÆÄÀÏ°ú zipÈ®ÀåÀÚ¸¦ °¡Áø ÆÄÀϸ¸ ¾÷·Îµå°¡ µÇµµ·Ï ÇÏ°í, ¿ë·®Àº 5¸Þ°¡¹ÙÀÌÆ® ¹Ì¸¸À¸·Î Á¦ÇÑÇÏ°Ú½À´Ï´Ù.

´ÙÀ½Àº Ǫ½Ã¸Þ¼¼Áö ±â´ÉÀ» ½ÃÀÛÇÏ°Ú½À´Ï´Ù!

service firebase.storage {
match /b/{bucket}/o {
match /{yyyyMMdd}/{roomId}/{userUid}/{file} {
allow read: if request.auth!=null;
allow write: if request.auth!=null
&& request.auth.uid == userUid
&& (request.resource.contentType.matches('image/.*') || file.matches(".*.zip"))
&& request.resource.size < 5 * 1024 * 1024;
}
}
}
view rawstorage.rules hosted with ❤ by GitHub


éÅÍ ¿Ï¼º ¼Ò½º  :




  1. ¿¹Á¦ ¼Ò°³
  2. Firebase ¼³Á¤Çϱâ
  3. HostingÀ» È°¿ëÇÑ ÇÁ·ÎÁ§Æ® Áغñ ÀÛ¾÷
  4. AuthenticationÀ» ÀÌ¿ëÇÑ À¯Àú °¡ÀÔ ¹× ·Î±×ÀÎ ±¸ÇöÇϱâ
  5. Realtime Database¸¦ ÀÌ¿ëÇÑ Ã¤Æñâ´É ±¸Çö - Reatime Database Ư¡ ¹× µ¥ÀÌÅÍ ±¸Á¶
  6. Realtime Database¸¦ ÀÌ¿ëÇÑ Ã¤Æñâ´É ±¸Çö - À¯Àúµ¥ÀÌÅÍ ÀúÀåÇϱâ
  7. Realtime Database¸¦ ÀÌ¿ëÇÑ Ã¤Æñâ´É ±¸Çö - À¯Àú¸®½ºÆà ȭ¸é
  8. Realtime Database¸¦ ÀÌ¿ëÇÑ Ã¤Æñâ´É ±¸Çö - äÆÃÈ­¸é ¹× äÆø޼¼Áö ¸®½ºÆÃ
  9. Realtime Database¸¦ ÀÌ¿ëÇÑ Ã¤Æñâ´É ±¸Çö - äÆø޼¼Áö Àü¼Û±â´É
  10. Realtime Database¸¦ ÀÌ¿ëÇÑ Ã¤Æñâ´É ±¸Çö - äÆÃ¹æ ¸®½ºÆÃÈ­¸é
  11. Realtime Database¸¦ ÀÌ¿ëÇÑ Ã¤Æñâ´É ±¸Çö - äÆùæ ÃÊ´ë ±â´É
  12. Realtime Database¸¦ ÀÌ¿ëÇÑ Ã¤Æñâ´É ±¸Çö - Á¢¼Ó ÁßÀÎ À¯Àú Ç¥½ÃÇϱâ
  13. Storage¸¦ ÀÌ¿ëÇÑ ÆÄÀÏ Àü¼Û±â´É
  14. Cloud Messaging°ú FunctionsÀ» ÀÌ¿ëÇÑ Çª½Ã¸Þ¼¼Áö ±â´É - FCM Token Á¤º¸ ÀúÀå
  15. Cloud Messaging°ú FunctionsÀ» ÀÌ¿ëÇÑ Çª½Ã¸Þ¼¼Áö ±â´É - Functions¸¦ ÅëÇÑ FCM ¹ß¼Û
  16. Cloud Messaging°ú FunctionsÀ» ÀÌ¿ëÇÑ Çª½Ã¸Þ¼¼Áö ±â´É - Service worker¸¦ ÀÌ¿ëÇÑ FCM¼ö½Å
  17. Realtime Database ±ÇÇÑ ¼³Á¤



Ãâó: http://cionman.tistory.com/63 [Suwoni-Codelab]