티스토리 뷰
1) file upload방법의 이해
file upload
- form태그의 데이터를 보낼 때, file도 input 방식으로 업로드가 가능합니다. file type에도 name으로 이름을 지정해야 서버에서 이를 인식해서 데이터를 얻을 것입니다.
- 이전처럼 문자열 기반의 데이터를 보내는 것과는 다르게 file은 바이너리 형태의 데이터를 보냅니다.
- 아래는 input type이 file인 경우 예제입니다.
<input type="file" name="reviewImg" id="reviewImageFileOpenInput" accept="image/*"> |
- 클라이언트 입장에서는 file을 올린다고 해서 크게 다르진 않습니다. input의 type을 file로 설정하고 name설정을 해서 클라이언트/서버 간의 보낼 데이터의 이름을 지어주면 됩니다. 그리고 서버는 해당 name을 기준으로 클라이언트가 보낸 데이터들을 구분해서 처리합니다.
- id는 클라이언트에서만 처리하거나 제어할 때 필요한 것입니다. 예를 들어서 input type의 어떤 이벤트를 등록을 하고 싶을 때 사용합니다.
- accept는 허용 가능한 file type을 결정지을 수 있습니다. 예를 들어 위와 같이 설정하면 이미지 파일을 제외한 텍스트 파일 등은 업로드할 수 없습니다. 이와 관련해 유용한 속성이 여러 개 있는데, 브라우저 지원이 제한적인 상태이므로 참고해서 사용해야 합니다. caniuse.com 같은 사이트에서 브라우저 지원 범위를 확인할 수 있습니다. accept는 다중으로 설정할 수 있습니다. (ex) accept="image/png, image/jpeg")
<div class="formWrap"> <form action="/join" method="post" id="myform"> <div class="inputWrap"> <div class="email"> <span> Email </span> <input type="text" name="email"><br/> </div> <div class="password"> <span> Password </span> <input type="password" name="password"><br/> </div> <input type="file" name="reviewImg" accept="image/*"> </div> <input class="sendbtn" type="submit"> </form> </div> |
위와 같이 파일 선택을 누르면 오른쪽 창이 나타나고 설정한대로 image 파일만 넣을 수 있도록 되어 있습니다. 파일을 선택하여 열기를 누르면 DOM으로 조작을 하지 않아도 화면에 자동으로 추가됩니다. 하지만 submit을 하지 않은 상태이므로 아직 서버에는 날아가지 않고 클라이언트단에서만 이렇게 보입니다. |
- 이렇게 해서 서버로 날아간 input(file)은 일반적인 태그들과는 Content-Type이 다릅니다.
- 일반적인 form 데이터를 전송 시에 HTTP Header에는 기본적으로, 'application/x-www-form-urlencoded' 라는 정보로 노출 됩니다. (ex) Content-Type:application/x-www-form-urlencoded)
- 그런데, file을 전송할 때는 좀 다릅니다. 아래처럼 Form 태그의 속성으로, enctype를 multipart/form-data로 지정해야 합니다. (ex) Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7rKYKhIWaTrjvGi1)
- 여기서 다루지는 않지만, 서버에서는 multipart/form-data를 처리할 수 있도록 합니다. 그래야 바이너리 형태로 데이터를 전송할 수 있습니다.
<div class="formWrap"> <form action="/join" method="post" id="myform" enctype="multipart/form-data"> <div class="inputWrap"> <div class="email"> <span> Email </span> <input type="text" name="email"><br/> </div> <div class="password"> <span> Password </span> <input type="password" name="password"><br/> </div> <input type="file" name="reviewImg" accept="image/*"> </div> <input class="sendbtn" type="submit"> </form> </div> |
- multipart/form-data의 실제 데이터를 서버로 어떻게 전송이 될까요? 크롬 개발자도구의 network탭에서 요약된 정보를 통해서 이를 이해할 수 있습니다. 서버에서는 multipart나 boundary를 통해 파싱을 해서 데이터를 뽑고 추출을 합니다.
------WebKitFormBoundaryiUIOhJXAwxorM25j Content-Disposition: form-data; name="email"
werwerw@sefdsf.com ------WebKitFormBoundaryiUIOhJXAwxorM25j Content-Disposition: form-data; name="password"
werwerwerwerwer ------WebKitFormBoundaryiUIOhJXAwxorM25j Content-Disposition: form-data; name="reviewImg"; filename="A_Pen_by_younjisu.png" Content-Type: image/png
------WebKitFormBoundaryiUIOhJXAwxorM25j-- |
- 특이한 점은, 아래와 같이 WebKitFormBoundaryiUIOhJXAwxorM25j 라는 어떤 구분정보를 기준으로 데이터가 노출되고 있습니다. 다른 input 데이터들과 같이 서버로 보내야 한다면, 아래와 같이 html페이지를 구성할 수 있을 겁니다.
- 실제로는 파일을 보낼 때는, 보통 다른 데이터와 별도로, 먼저 보내는 경우도 많습니다.
생각해보기
- file upload를 Ajax기술로 구현할 수 있을까요? -> 네 가능합니다. (ex) FormData 속성)
- 약간 더 복잡한 처리를 해야하지만, FormData라는 속성을 이용하면 좀더 쉽게 구현할 수가 있습니다. 여기를 참고하세요
참고 자료
[참고링크] Using FormData Objects
[참고링크] file input 처리하는 방식 설명
https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/file
[참고링크] multipart 보낼때 데이터 구분에 대한 내용
https://stackoverflow.com/questions/4526273/what-does-enctype-multipart-form-data-mean
'부스트코스 웹 프로그래밍 > 6. 웹 앱 개발: 예약서비스 4' 카테고리의 다른 글
3. 파일 업로드 & 다운로드 - BE (1) (0) | 2019.08.13 |
---|---|
2. 로깅 - BE (3) (0) | 2019.08.13 |
2. 로깅 - BE (2) (0) | 2019.08.13 |
2. 로깅 - BE (1) (0) | 2019.08.13 |
1. 파일 업로드 - FE (2) (0) | 2019.08.13 |