본문 바로가기
FRONTEND/Code Backup

210610 Javascript - File / Blob / 업로드 / 다운로드 / Encoding / Decoding

by 또야또야 2021. 11. 25.
반응형

Blob 이란?

Blob Objectfile 같은 나열할 수 있는(Enumerable) 오브젝트이며, raw data 입니다
Text 나 binary data 처럼 읽힐 수 있고, ReadableStream 으로 변환될 수 있습니다.

FileList 와 File 의 생김새 차이

console 로 확인해보면, FileListFile 의 생김새의 차이는 아래와 같습니다.

- FileList : { 0: File, length: 1 } 
- File : { name: 'svg.svg', lastModified: 1631689538013, size: 191, ... }

FileReader 사용하기

Image 를 Base64 코드로 변환하기

const file = document.querySelector('input[type="file"]').files[0];

const reader = new FileReader()
reader.readAsDataURL(file)
reader.onload = () => {
  console.log(reader.result)
}
// Promise 를 이용하는 방법
function getBase64(file) {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.readAsDataURL(file);  // 인코딩
    reader.onload = () => resolve(reader.result);
    reader.onerror = error => reject(error);
  });
}

getBase64(file)
  .then(data => console.log(data))

Base64 코드를 Image 로 변환하기

// base64 image 형식
const imageURL = 'data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAkGBxMTEhUTExIVFRUWGBcVGBgYGBgYFRcXGBcWFxUWGBgYHSggGBolHRcVITEhJSkrLi4uFx8zODMtNygtLisBCgoKDg0OGhAQGyslHyUtLS0tLS01LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLf/AABEIAJ8BPgMBIgACEQEDEQH/xAAcAAACAwEBAQEAAAAAAAAAAAAFBgIDBAcBAAj/xABAEAABAgQEAwUGAwgBBAMBAAABAhEAAwQhBRIxUUFhcQYTIoGRMqGxwdHwFEJSFSNicoKSouEHM0PC8SSTshb/xAAaAQACAwEBAAAAAAAAAAAAAAACAwEEBQAG/...
'

convertBase64IntoFile(imageURL, 'cat.jpeg')
/**
 * 파일을 Base64 형식에서 > File 형식으로 (디코딩)변환합니다
 * @param { String } image Base64 형식의 String
 * @param { String } fileName Base64 에서는 파일 명을 저장할 수 없습니다.
 */
convertBase64IntoFile (image, fileName) {
  const mimeType = image?.match(/[^:]\w+\/[\w-+\d.]+(?=;|,)/)[0]   // image/jpeg
  const realData = image.split(',')[1]   // 이 경우에선 /9j/4AAQSkZJRgABAQAAAQABAAD...

  const blob = b64toBlob(realData, mimeType)
  const raw = new File([blob], fileName, { type: mimeType })

  const fileList = [{ name: raw.name, size: raw.size, uid: 1, raw }]
  return fileList
},
/**
 * base64 를 Blob 오브젝트로 만드는 함수
 * @param { String } b64Data
 * @param { String } contentType mimeType
 * @param { Number } sliceSize 쪼개는 사이즈
 */
b64toBlob (b64Data, contentType = '', sliceSize = 512) {
  if (b64Data === '' || b64Data === undefined) return

  const byteCharacters = atob(b64Data)
  const byteArrays = []

  for (let offset = 0; offset < byteCharacters.length; offset += sliceSize) {
    const slice = byteCharacters.slice(offset, offset + sliceSize)
    const byteNumbers = new Array(slice.length)
    for (let i = 0; i < slice.length; i++) {
      byteNumbers[i] = slice.charCodeAt(i)
    }
    const byteArray = new Uint8Array(byteNumbers)
    byteArrays.push(byteArray)
  }

  const blob = new Blob(byteArrays, { type: contentType })
  return blob
}

파일 내부 데이터를 텍스트로 변환하기

const reader = new FileReader()
reader.readAsText(file)   // file 은 '.txt' 확장자를 가지는 업로드된 파일(File 형식)라고 가정합니다
reader.onload = () => {
  console.log(reader.result)
}

파일 업로드

async function fileUpload (raw) {
  const formData = new FormData()
  formData.append('file', file)
  const url = await API.sampleURI(formData) // API 로 파일 전송

  console.log(formData.get('file')) // 'file' 에 대한 정보를 확인합니다.
}

파일 다운로드

// 첨부파일이 있는경우 클릭시 다운로드합니다.
function downloadFild () {
  // 서버에서 URL 을 내려주는 경우
  const downloadLocation = `${process.env.VUE_APP_ZULE_URL}/api/example/file/download_location}`
  return window.location.assign(downloadLocation)
}

//  임의로 a 태그를 만들어 실행시킵니다.
function downloadURI(uri, name) {
  var link = document.createElement('a')
  link.download = name
  link.href = uri
  document.body.appendChild(link)
  link.click()
  document.body.removeChild(link)
  delete link
}

부록 - 파일 용량 체크

function fileSizeCheck (file) {
 if (file.size > (1024 * 1024 * 1024 * 5)) { // 5GB 이하 파일만 업로드 가능
    return alert('5GB 이하인 파일만 업로드 가능합니다.')
  } 
}
반응형

댓글