파일업로드

[파일업로드] Ajax 방식

레파캣 2016. 9. 11. 16:05

파일업로드 Ajax 방식의 핵심은 FormData 라는 브라우저에서 지원하는 클래스이다. 

 

FormData 는 <form> 과 같은 효과를 가져다주는 key/value 가 저장되는 객체이다. <form> 태그처럼 데이터를 처리할 수 있게 해준다. 이를 XHR 에 실어서 서버에 보내면 마치 <form> 이 전송된 것과 같은 효과를 가져다 준다.

 

IE 에서는 10 부터 지원한다고 한다. (참고)

 

사용자가 선택한 File 을 아래와 같이 FormData 에 추가할 수 있다.

검색해보니 좋은 예제가 있어 복사했다. (출처는 여기)

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
$('drag-target-selector').on('drop'function(event) {
 
 //stop the browser from opening the file
 event.preventDefault();
 
 //Now we need to get the files that were dropped
 //The normal method would be to use event.dataTransfer.files
 //but as jquery creates its own event object you ave to access 
 //the browser even through originalEvent.  which looks like this
 var files = event.originalEvent.dataTransfer.files;
 
 //Use FormData to send the files
 var formData = new FormData();
 
 //append the files to the formData object
 //if you are using multiple attribute you would loop through 
 //but for this example i will skip that
 formData.append('files', files[0]);
 
 }
cs

 

사용자가 파일을 Drag & Drop 했을 때의 처리에 대한 내용이다. 

 

브라우저에 어떤 파일을 drop 하면 브라우저 기본 동작이 실행된다. 이미지를 drop 하면 바로 표시되고 pdf 파일의 경우도 각 브라우저의 pdf viewer 로 브라우저 내에서 문서를 열어 보여준다. 이를 방지하기 위해 preventDefault() 를 호출한다. 

 

그 다음 이벤트에서 file 정보를 받아온다. drag & drop 동작에서 파일 정보는 DataTransfer 라는 객체를 통해 얻어올 수 있다. 스펙은 여기에 있는데, 여러가지 기능을 제공하고 있다. files 라는 프로퍼티를 참고하자. 이것도 IE 는 10 이상에서 지원된다고 한다.

 

이렇게 얻은 파일 정보를 formData.append() 를 통해 key/value 형식으로 넣는다. 최종적으로 jQuery의 Ajax API를 통해 전송하면 된다.

 

1
2
3
4
5
6
7
8
9
10
        $.ajax({
            url: '/uploadAjax',
            data: formData,
            dataType: 'text',
            processData: false,
            contentType: false,
            type: 'POST',
            success: function(data) {
            }
        );
cs

 

파라미터 중 dataType, processData, contentType 을 보자. 

 

dataType 은 내가 보내는 데이터의 타입이 아니고 서버가 응답(response)할 때 보내줄 데이터의 타입이다. 이는 success function 에 전달될 argument 의 형태를 지정하는데 사용된다고 한다. (참고)

 

processData 관련하여, 일반적으로 서버에 전달되는 데이터는 query string 이라는 형태로 전달된다. (아래 빨간 부분)

 

ex) http://example.com/over/there?title=Main_page&action=raw

 

data 파라미터로 전달된 데이터를 jQuery 내부적으로 query string 으로 만드는데, 파일 전송의 경우 이를 하지 않아야 하고 이를 설정하는 것이 processData: false 이다.

 

contentType 은 default 값이 "application/x-www-form-urlencoded; charset=UTF-8" 인데, "multipart/form-data" 로 전송이 되게 false 로 넣어준다. false 로 넣어주는 것이 언뜻 이해가 안되서 false 말고 "multipart/form-data" 를 넣어봤는데 boundary string 이 안들어가게 되어 제대로 동작하지 않았다.

 

파일을 전송해보면 content-type header 가 아래와 같이 설정된다.

 

  1. Content-Type:
    multipart/form-data; boundary=----WebKitFormBoundarybuOGBs9coioS5Kb9

 

boundary string 은 전송되는 데이터의 영역을 구분해주는 구분자로 브라우저에서 넣어주는 건데, contentType을 명시적을 설정할 경우 boundary string 을 overwrite 하게 되는게 아닌가 한다.