서버에 이미지 보내기 multi-formdata / blob

김태완·2022년 5월 29일
1

프론트엔드

목록 보기
22/30

컴포넌트를 캡쳐한 이미지를 서버로 보내는 업무를 맡았다. 이미지를 서버로..?? 바이너리 개념인 Blob과 서버에 보내는 방식중 multi-formdata에 대해서 알아보자

Blob이란?

  • Blob(Binary Large Object)란 바이너리 형태중에서도 큰 객체를 뜻하는데, 주로 이미지, 비디오, 사운드 같은 멀티미디어 객체를 나타낸다.
  • Blob은 4GB의 이진데이터의 위치포인터를 DB에 저장한다.

사용법

아래처럼 배열과 타입을 넣어 객체를 생성한다

var blob = new Blob([typedArray], {type: "application/octet-binary"})
var audioBlovb = new Blob([dataView], {type:type})

아래처럼 URL을 생성할 수 있는데 이 URL을 a태그에 연결하여 다운(서버X 브라우저O)받을 수 있다.

var reader = new FileReader();
reader.readAsArrayBuffer(blob);
//FileReader를 통해서 blob을 읽을 수 있다.

Multi-FormData

  1. 서버에 이미지를 보내기위해서는 브라우저에서 form을 통해서 파일을 전송한다.
  2. 브라우저에서 보내는 HTTP메시지는 Content-Type속성이 multipart/form-data로 지정되며 정해진 형식에 따라 메시지를 인코딩한다
  3. 서버에서는 해당 메시지에 대해 각 파트별로 분리하여 개별 파일의 정보를 얻는다

이때 이미지 파일도 문자로 이루어져있으므로 HTTP Request Body에 이미지 파일을 문자형식으로 담아 보낸다!

form

  • name : form의 이름, 서버로 보내질 이름값
  • action : form이 전송되는 서버 url
  • method : 전송방법, default로 get.
  • autocomplete : 자동완성기능
  • enctype : 폼 데이터가 서버로 제출될때 해당 데이터가 인코딩 되는 방법을 명시한다

enctype

  • application/x-www-form-urlencoded

    default값으로 모든 문자들을 서버로 보내기전에 인코딩됨을 명시함

  • text/plain

    공백문자는 "+"로 변환, 나머지 문자는 인코딩하지않음을 명시

  • multipart/form-data (핵심!)

    모든 문자들을 인코딩하지않음을 명시함. 이 방식은 <form>요소가 파일이나 이미지를 서버로 전송할때 주로 사용한다. 또한 요청시 POST로 보내야한다.

    <form action="/home/uploadfiles" method="post" enctype="multipart/form-data">
       파일명 : <input type="file" name="myfile">
       <button type="submit">제출하기</button>
    </form>

    Multipart가 생긴배경

    HTTP Request는 Body에 클라이언트가 전송하려는 데이터를 넣을 수있다
    Body에 들어가는 데이터의 타입을 HTTP Header에 명시해줌으로써 서버가 타입에 따라 알맞게 처리하게 한다.
    이 Body의 타입을 명시하는 Header가 Content-Type이다

    그런데 여기서 Content-Type은 한가지의 타입만 명시할수있다.

    만약 "이미지 + 이미지에대한 설명"과 같이 다중 데이터가 들어가야할때를 위해 multipart가 생겨났다.

예제코드

const handleSubmit = (e) => {
    e.preventDefault();
    const formData = new FormData();
    formData.append("photo", files.length && files[0].uploadedFile);
    formData.append("comment", commentValue);
    formData.append("content_id", classData.content_id);

    axios({
      method: "post",
      url: process.env.REACT_APP_STREAMING_COMMENT_URL, //환경변수
      data: formData,
      headers: { "Content-Type": "multipart/form-data", Authorization: localStorage.getItem("access_token") }
    });
    setCommentValue("");
    setFiles([]);
  };

  const handleUpload = (e) => {
    e.preventDefault();
    const file = e.target.files[0];
    setFiles([...files, { uploadedFile: file }]);
  };
profile
프론트엔드개발

0개의 댓글