[CS] Multipart/form-data

Youngwoo Lee·2021년 11월 10일
1

CS

목록 보기
5/5
post-thumbnail

Multiapart Form Data

HTTP 헤더에서는 content-type 이라는 것을 줄 수 있다. 이는 resource 들의 media type을 타나내기 위함이다. media type은 MIME type 과 동일하다

그에 따라, 우리는 content-type 으로 MIME type 중 하나인 multipart/form-data 으로 설정할 수 있다. 파일 업로드를 구현할 때, 클라이언트는 폼을 통해서 파일을 등록해서 전송하게 되며, 이를 처리하기 위한 서버는 멀티파트 메시지에 대해서 각 파트별로 분리하여 개별 파일의 정보를 얻게 된다

이해가 어렵다면... 더 자세하게 알아보자!

HTTP(request와 response)는 간단하게 위 이미지와 같이 4개의 파트로 나눌 수 있습니다. 

HTTP Header

  • 여기서 Message Body에 들어가는 데이터 타입을 명시해줄 수 있습니다.
  • 이를 명시할 수 있도록 해주는 필드가 바로 Content-type입니다. 추가적으로 Content-type 필드에 MIME(Multipurpose Internet Mail Extensions) 타입을 기술해줄 수 있는데, 여러 타입 중 하나가 바로 multipart 이다
Content-Type: multipart/form-data; boundary=3A42CBDB-01A2-4DDE-A9EE-425A344ABA13

< MIME에서의 multipart & multipart/form-data >
클라이언트가 서버에게 파일을 업로드할 때, http 프로토콜의 바디 부분에 파일 정보를 담아서 전송을 하는데, 파일을 한번에 여러 개 전송을 하면 body 부분에 파일이 여러 개의 부분으로 연결되어 전송된다. 이렇게 여러 부분으로 나뉘어서 전송되는 것을 Multipart data라고 한다

  • 보통 파일이나 사진을 전송할 때 사용한다
//http body 부분

--Boundary-3A42CBDB-01A2-4DDE-A9EE-425A344ABA13
Content-Disposition: form-data; name="family_name"

Wals
--Boundary-3A42CBDB-01A2-4DDE-A9EE-425A344ABA13
Content-Disposition: form-data; name="name"

Donny
--Boundary-3A42CBDB-01A2-4DDE-A9EE-425A344ABA13
Content-Disposition: form-data; name="file"; filename="somefilename.jpg"
Content-Type: image/png

-a long string of image data-
--Boundary-3A42CBDB-01A2-4DDE-A9EE-425A344ABA13—

multipart 타입을 통해 MIME은 트리 구조의 메세지 형식을 정의할 수 있습니다.

ex) 어떤 것이 첨부된 텍스트(multipart/mixed) /

텍스트와 HTML과 같이 다른 포맷을 함께 보낸 메세지(multipart/ alternative) 등

  • [ Multipart 메세지 ]
    • 서로 붙어있는 여러 개의 메세지를 포함하여 하나의 복합 메세지로 보내집니다.
    • MIME multipart 메세지는 “Content-type:” 헤더에 boundary 파라미터를 포함합니다.
    • boundary는 메세지 파트를 구분하는 역할을 하며, 메세지의 시작과 끝 부분도 나타납니다.
    • 첫번째 Boundary 전에 나오는 내용은 MIME을 지원하지 않는 클라이언트를 위해 제공됩니다.
    • boundary 를 선택하는 것은 클라이언트의 몫입니다. 보통 무작위의 문자를 선택해 메세지의 본문과 충돌을 피합니다. Ex) UUID
    • 멀티파트 폼 제출:
    • HTTP form을 채워서 제출하면, 가변 길이 텍스트 필드와 업로드 될 객체는 각각 멀티파트 본문을 구성하는 하나의 파트가 되어 보내집니다. 멀티 파트 분몬은 여러 다른 종류와 길이의 값으로 채워진 form을 허용합니다.
    • multipart/form-data: 사용자가 양식을 작성한 결과 값의 집합을 번들로 만드는데 사용합니다.

요약
1. 우리는 HTTP를 통해 전송할때 source를 실어서 보낼 수 있는데, 그 source의 media type을 정해주기 위해서 HTTP header에 MIME Type을 Content-Type 항목에 넣어서, 어떤 media type인지 명시해준다. 그 중에 multipart/form-data 가 있다
2. media type의 경우 body 부분에 여러 개의 파일을 실을 때 body를 여러 body로 나누기 편한 형식을 가지고 있다
3. 우리는 HTTP header에서 Content-Type을 채울때, boundary라고 하는 파라미터도 같이 채워야 하는데, 이 boundary 값은 본문의 내용에 절대 포함되지 않을만한 무작위 문자열이여야 하며, 보통 swift 에서는 UUID값을 사용한다
4. 해당 boundary 값을 통해서 우리는 body의 여러 파일들을 구분하는 구분자 역할로 사용한다


HTTP Body

이제 body에 file을 실어보는 작업을 해보자!

Content-Header

Body에도 각 content의 정보를 나타내는 header가 따로 존재하는데, 이를 Content-Header 라고 한다.

  1. Content-Disposition : multipart/form-data 본문에서의 Content-Disposition 일반 헤더는 multipart의 하위파트에서 활용될 수 있는데, 이 때 이 헤더는 multipart 본문 내의 필드에 대한 정보를 제공합니다.

    multipart의 body를 위한 헤더로는 언제나 form-data 가 들어가야 됩니다

Content-Disposition: form-data
  1. name

    이름(name) 다음에 오는 문자열에는 이 서브파트가 참조하는 폼의 필드에서 사용한 그 이름이 들어갑니다.

  2. filename

    파일명(filename) 다음에 오는 문자열에는 전송된 해당 파일의 원래 이름이 들어갑니다. 파일명은 언제나 선택사항이지만, 맹목적으로 쓰여서는 안됩니다

  3. Content-Type

    HTTP Header 에서도 Content-Type을 지정했지만 Content-Header 에서의 MIME type 는 해당 content의 미디어 타입을 지정하는 것이다

name, filename, Content-Type 는 optional 이다

POST /test.html HTTP/1.1
Host: example.org
Content-Type: multipart/form-data;boundary="boundary"

--boundary
Content-Disposition: form-data; name="field1"

value1
--boundary
Content-Disposition: form-data; name="field2"; filename="example.txt"

value2
--boundary--

구분자

  1. 전송되는 파일 데이터의 구분자로는 Content-Type 에서 지정한 boundary 문자열을 이용합니다.
  2. body의 가장 마지막은 -- 로 끝나며, 이는 body의 끝을 알리는 의미를 가집니다.
  3. 추가적으로 header 와 header 를 구분하는 것은 개행문자이고, header 와 body 를 구분하는 것은 개행 문자 2개, body 에 포함되어있는 file data 를 구분하는 것은 boundary입니다.

엄밀하게는 (개행)바운더리문자열(개행)을 기준으로 구분하게 됩니다. 또, 이때의 개행은 플랫폼에 상관없이 CRLF로 \r\n을 사용해야 합니다.

참고자료

CodingNotes-MultiPart란?
레나-HTTP multipart/form-data 이해하기

profile
iOS Developer Student

0개의 댓글