그럼에도 불구하고

👨‍💻

FileReader 객체 사용하여 image 올리기 본문

JavaScript/Function implementation

FileReader 객체 사용하여 image 올리기

zenghyun 2023. 1. 5. 23:41

FileReader 객체 사용하여 image 올려보자

 

 

ref: 

 

[JavaScript] FileReader 객체에 대해 알아보자

FileReader란 무엇인가? [ FileReader란? ] FileReader란 type이 file인 input 태그 또는 API 요청과 같은 인터페이스를 통해 File 또는 Blob 객체를 편리하게 처리할 수 있는 방법을 제공하는 객체이다. abort, load, e

despiteallthat.tistory.com

1. 파일을 올릴 수 있는 버튼을 누르면 파일을 올린다.

2. 올릴 파일은 image로 제한한다.

3. 파일은 한 개만 올릴 수도 있고 다수도 가능하다. (여기서는 4개)

4. 각 파일마다 파일명, 사이즈, 파일타입을 알려준다. 

 

 

CSS

더보기
* {
      margin: 0;
      padding: 0;
    }

    body {
      margin: 20px;
    }

    #image {
      display: none;
    }

    .form-container {
      display: flex;
      margin: 20px 0;
      gap: 20px;
    }

    .img-upload-btn {
      display: inline-block;
      width: 200px;
      height: 50px;
      background-color: skyblue;
      border-radius: 10px;
      cursor: pointer;
      text-align: center;
      line-height: 50px;
      box-shadow: inset 0 0 10px rgb(106, 170, 196);
    }

    #fileName-preview {
      width: 400px;
      height: 50px;
      border-radius: 10px;
      background-color: #feefef;
      text-indent: 1rem;
      border: 1px solid #fddfdf;
    }

    .log {
      display: flex;
      gap: 70px;
    }

    .img-preview {
      display: flex;
      justify-content: space-evenly;
      width: 2200px;
      height: 540px;
      box-sizing: content-box;
      border: 10px solid black;
      border-radius: 50px;
    }

    .img-preview img {
      margin: 20px;
      width: 500px;
      height: 500px;
      gap: 50px;
      border: 3px solid slategray;
      border-radius: 30px;
    }
 l;kl;kl

 

HTML

더보기
  <h1>이미지 미리보기</h1>
  <div class="form-container">
    <input type="text" id="fileName-preview" disabled placeholder="파일을 선택하세요.">
    <label for="image" class="img-upload-btn"> 이미지업로드 </label>
    <input type="file" id="image" accept="image/*" multiple>
    <!-- 여러개 파일 업로드  -->
  </div>
  <div class="log"></div>
  <div class="img-preview">
    <!-- <img src="" alt=""> -->
  </div>

 

JavaScript

  <script>

    const getFileBtn = document.querySelector('#image');

    getFileBtn.addEventListener('change', (event) => {
      let route = event.srcElement.files;

      document.querySelector('#fileName-preview').value = (`
            ${route[0].name}외 ${route.length - 1}개 선택
            `).trim();

      for (let i = 0; i < route.length; i++) {
        log.innerHTML += `
            <div>상세정보</div>
            파일명 : ${route[i].name} <br>
            사이즈 : ${sizeCalculater(route[i].size)} <br>
            파일타입 : ${route[i].type}
        `
      }

      const imgPreview = document.querySelector('.img-preview');
      imgPreview.innerHTML = "";
		
        // route를 배열화 
      [...route].forEach((data) => {
        if (data.type.includes('image')) {
          // 파일 제한을 둬서 이미지만 골라서 출력 
          const fileReader = new FileReader();
          fileReader.readAsDataURL(data);
          fileReader.addEventListener('load', (event) => {
            const img = document.createElement('img');
            img.setAttribute('src', event.target.result);
            imgPreview.appendChild(img);
          })
        }
      })

    })

    // 메모리에 바이널리 코드로 저장 했다가 바꿔주는 작업 
    function sizeCalculater(size) {
      const UNIT = 1024;
      
      if (size <= UNIT) {
        return size + 'byte'
      } else if (size > UNIT && size <= UNIT ** 2) {
        return (size / UNIT).toFixed(1) + "KB"
      } else if (size > UNIT ** 2 && size <= UNIT ** 3) {
        return (size / UNIT**2).toFixed(1) + "MB"
      } else if (size1 > UNIT ** 3 && size <= UNIT ** 4) {
        return (size / UNIT**3).toFixed(1) + "GB"
      }
    }

  </script>

 

 

자주 사용하는 경로는 여러번 쓰지 않고 변수로 초기화시켜 사용한다. 

let route = event.srcElement.files;

 


내가 upload한 file명과 상세정보를 보여준다.

 document.querySelector('#fileName-preview').value = (`
            ${route[0].name}외 ${route.length - 1}개 선택
            `).trim();

      for (let i = 0; i < route.length; i++) {
        log.innerHTML += `
            <div>상세정보</div>
            파일명 : ${route[i].name} <br>
            사이즈 : ${sizeCalculater(route[i].size)} <br>
            파일타입 : ${route[i].type}
        `
      }

 

 

route를 배열화하여 이미지를 upload 한다. 

    // route를 배열화 
    [...route].forEach((data) => {
      if (data.type.includes('image')) {
        // 파일 제한을 둬서 이미지만 골라서 출력 
        const fileReader = new FileReader();
        fileReader.readAsDataURL(data);
        fileReader.addEventListener('load', (event) => {
          const img = document.createElement('img');
          img.setAttribute('src', event.target.result);
          imgPreview.appendChild(img);
        })
      }
    })

 

상세정보 업로드시 용량을 바이트 단위로 환산한다.

    // 메모리에 바이널리 코드로 저장 했다가 바꿔주는 작업 
    function sizeCalculater(size) {
      const UNIT = 1024;

      if (size <= UNIT) {
        return size + 'byte'
      } else if (size > UNIT && size <= UNIT ** 2) {
        return (size / UNIT).toFixed(1) + "KB"
      } else if (size > UNIT ** 2 && size <= UNIT ** 3) {
        return (size / UNIT**2).toFixed(1) + "MB"
      } else if (size1 > UNIT ** 3 && size <= UNIT ** 4) {
        return (size / UNIT**3).toFixed(1) + "GB"
      }
    }

 

 

결과

See the Pen Untitled by zenghyun (@zenghyun) on CodePen.

 

 

개선

JavaScript 코드가 비효율적으로 보였다.

getFileBtn을 눌렀을 때 'change' event가 발생하는 구문안에 다수의 기능이 들어 있었다. 

 

1. 함수로 나눠서 하나의 함수는 하나의 기능만 하게 바꾼다.

2. 상세정보를 upload할 때 for문을 사용하지 않고 route를 배열화 해서 upload 한다.

3. 이미지 upload시 [...route]와 같이 쓰지 않고 2번에서 route를 배열화한 객체를 사용한다.

 

 <script>
    "use strict";
    const getFileBtn = document.querySelector('#image');

    getFileBtn.addEventListener('change', (event) => {
      let route = event.srcElement.files;
      const routeAry = Array.from(route);
      let fileName = document.querySelector('#fileName-preview');

      fileName.value = (`
            ${route[0].name}외 ${route.length - 1}개 선택
            `).trim();

      showLog(routeAry);
      showImg(routeAry);
    })
    
    // upload한 정보 
    function showLog(routeAry) {
      const log = document.querySelector('.log');

      routeAry.forEach((value) => {
        log.innerHTML += `
                <div>상세정보</div>
                파일명 : ${value.name} <br>
                사이즈 : ${sizeCalculater(value.size)} <br>
                파일타입 : ${value.type}
            `;
      })
    }
    
    // upload한 image 
    function showImg(routeAry) {
      const imgPreview = document.querySelector('.img-preview');
      imgPreview.innerHTML = "";

      routeAry.forEach((data) => {
        if (data.type.includes('image')) {
          // 파일 제한을 둬서 이미지만 골라서 출력 
          const fileReader = new FileReader();
          fileReader.readAsDataURL(data);

          fileReader.addEventListener('load', (event) => {
            const img = document.createElement('img');
            img.setAttribute('src', event.target.result);
            imgPreview.appendChild(img);
          })
        }
      })

    }
    
    // 메모리에 바이널리 코드로 저장 했다가 바꿔주는 작업 
    function sizeCalculater(size) {
      const UNIT = 1024;

      if (size <= UNIT) {
        return size + 'byte'
      } else if (size > UNIT && size <= UNIT ** 2) {
        return (size / UNIT).toFixed(1) + "KB"
      } else if (size > UNIT ** 2 && size <= UNIT ** 3) {
        return (size / UNIT**2).toFixed(1) + "MB"
      } else if (size1 > UNIT ** 3 && size <= UNIT ** 4) {
        return (size / UNIT**3).toFixed(1) + "GB"
      }
    }
  </script>

 

결과는 동일하게 나오지만 이게 더 명료하고 가독성도 좋은 것 같다.

Comments