HTTP multipart/form-data raw 데이터는 어떤 형태일까?

프로그래밍|2014. 6. 30. 14:47

Apache HTTP Client를 이용하여 multipart/form-data content-type으로의 요청을 서버로 보내는 유틸을 개발하게 되었다.

흔히 웹 브라우저에서 파일 첨부를 한 후 "저장하기" 버튼을 클릭했을 때의 동작을 Java 코드로 구현하는 것 뿐이다.


client와 server코드를 완성한 후 서버측으로 다음과 같은 정보로 요청을 보냈다.

request URL : http://localhost:8080/file/upload

업로드 파일 : test.txt, test1.txt


로그 레벨을 DEBUG로 설정한 후 파일 업로드 요청을 보내게 되면 다음과 같은 request raw 데이터가 남게 된다.

실제 client 에서는 다음과 같은 데이터를 서버로 보내게 되는 것이다.


multipart/form-data로 데이터를 보낼때의 request header와 body는 위와 같이 이뤄져 있으며 눈여겨 봐야 할 부분은 Content-Type이다.

Content-Type에 multipart/form-data로 지정이 되어 있어야 서버에서 정상적으로 데이터를 처리할 수 있으며 boundary에 지정되어 있는 문자열을 이용하여 전송되는 파일 데이터의 구분자로 사용되는 것을 확인할 수 있다.

boundary의 문자열 중 마지막의 ------WebKitFormBoundaryQGvWeNAiOE4g2VM5-- 값은 다른 값들과 다르게 마지막에 -- 가 붙은 것을 확인할 수 있는데 이는 body의 끝을 알리는 의미이다.


이러한 것들이 모두 HTTP 통신 규격으로 지정되어 있으며 이 규격에 맞게 http header와 body 데이터를 생성한 후 HTTP server에 요청하게 되면 서버에서도 HTTP 통신 규격에 맞게 데이터를 파싱한 후 처리하게 되는 것이다.


HTTP request와 response의 데이터를 좀더 자세하게 살펴보도록 하자.

다음은 개행 문자가 포함되어 있는 HTTP request와 response 이다.

헤더와 헤더를 구분하는 것이 개행문자임을 알 수 있고, 

헤더와 바디를 구분하는 것은 개행문자2개

body에 포함되어 있는 파일데이터를 구분하는 것은 boundary라는 것을 알 수 있다.

## HTTP Request Data

POST /file/upload HTTP/1.1[\r][\n]

Content-Length: 344[\r][\n]

Content-Type: multipart/form-data; boundary=Uee--r1_eDOWu7FpA0LJdLwCMLJQapQGu[\r][\n]

Host: localhost:8080[\r][\n]

Connection: Keep-Alive[\r][\n]

User-Agent: Apache-HttpClient/4.3.4 (java 1.5)[\r][\n]

Accept-Encoding: gzip,deflate[\r][\n]

[\r][\n]

--Uee--r1_eDOWu7FpA0LJdLwCMLJQapQGu[\r][\n]

Content-Disposition: form-data; name=files; filename=test.txt[\r][\n]

Content-Type: application/octet-stream[\r][\n]

[\r][\n]

aaaa

[\r][\n]

--Uee--r1_eDOWu7FpA0LJdLwCMLJQapQGu[\r][\n]

Content-Disposition: form-data; name=files; filename=test1.txt[\r][\n]

Content-Type: application/octet-stream[\r][\n]

[\r][\n]

1111

[\r][\n]

--Uee--r1_eDOWu7FpA0LJdLwCMLJQapQGu--[\r][\n]


## HTTP Response Data

HTTPHTTP/1.1 200 OK[\r][\n]

Server: Apache-Coyote/1.1[\r][\n]

Accept-Charset: big5, big5-hkscs, euc-jp, euc-kr...[\r][\n]

Content-Type: text/html;charset=UTF-8[\r][\n]

Content-Length: 7[\r][\n]

Date: Mon, 30 Jun 2014 01:28:19 GMT[\r][\n]

[\r][\n]

SUCCESS


Content-Length가 344byte로 데이터가 많지 않기 때문에 하나의 패킷에 담겨져(기본1500byte) 네트웍을 통해 서버로 갈 것인데 만약 첨부된 파일이 이미지라면 여러 개의 패킷으로 쪼개져 네트웍을 통해 서버에 도착하게 될 것이다.


이처럼 HTTP 통신 원리는 단순하다. 스펙에 맞게 문자를 생성한 후 전송되는 것 뿐이다. 이미지를 첨부한다고 해서 xxx.jpg 파일 자체가 전송되는 것이 아니고 동영상을 첨부한다고 해서 xxx.avi 파일 자체가 전송되는 것이 아니다. 이미지 파일 동영상 파일도 문자로 이루어져 있기 때문에 이 문자들이 HTTP request body에 담겨져 서버로 보내지게 되는 것 뿐이다.

간단한 원리로 데이터를 주고 받는 HTTP 프로토콜이지만 모르고 지나치지 않았으면 하는 생각에 정리한다.

댓글()