어떤 컨트롤러(URL)를 호출하면 바로 '파일 다운로드'로 파일을 다운로드 할 수 있게 하려고 한다.
그 전에 알아야 할 개념
아주 간단히 설명하고 넘어가겠음.
원론적인 설명이 아니라 이 포스팅을 설명하기 위한 좀 다른 시선의 얕은 설명이다.ㅎㅎ
(아는 분들은 Pass)
* MIME (Multipurpose Internet Mail Extensions) 문자열을 전송할 때는 7비트 아스키파일로 전송하여 사용하지만, 더 큰 음악, 사진 등의 파일을 보내는 경우는 8비트 데이터로(바이너리 데이터) 사용한다. 이 것을 전송하기 위해서는 바이너리 데이터를 텍스트로 변환하는 인코딩 작업이 필요하다. MIME은 이런 인코딩 방식의 일종이다. 이메일 시스템을 통해 파일을 전달하도록 개발되었다. 특정 데이터 타입을 받아 인코딩 한다. 즉, MIME은 인코딩 + data type(contents type) 이다. 데이터 type의 예를 들면 문자열이면 UTF-8이라던가, 미디어 type이면 h.264 divx 이런 것이 data type이다. |
* 바이너리 파일(Binary File) 컴퓨터가 이해할 수 있는 비트들의 연속으로 조합된 데이터. 예를들어, jpg 파일을 form을 통해 들고다니거나 업로드를 구현한다던가 할 때 contents type을 명시한다. http://www.sitepoint.com/web-foundations/mime-types-complete-list/ (위의 사이트에는 MIME Type 표준들이 명시되어있다) 여기 명시된 타입을 사용하면, 이 파일이 어떤 형태의 타입인지 알 수 있고, 표준처럼 사용을 할 수 있다. 그런데 바이너리 파일로 넘기면, 그 데이터 타입이 무엇인지 여부 상관없이 컴퓨터가 이해할 수 있는 비트로 된 그 파일을 통째로 넘기는 것이다. 순수한 파일 그 자체이다. 모든 파일은 바이너리로 되어있다. MIME type은 사람들이 사용하기 쉽도록 이미 알고 있는 컨텐츠타입을 명시해서 어떤 종류의 파일임을 알고 사용할 수 있도록 한 것. |
이번에 내가 구현한것은
1. 어드민이 다른 서버에서 파일을 받아오고
2. 그것을 어드민에서 txt 파일을 다운로드 시키는 것
인데
바이너리로 받아오려면 어떻게 해야할까??
Spring의 RestTemplate을 이용해서 Server to Server call을 할 때
아래와 같이 사용해서 바이너리 데이터를 받아온다.
HttpHeaders headers = new HttpHeaders(); headers.setAccept(Arrays.asList(MediaType.APPLICATION_OCTET_STREAM)); headers.setContentType(MediaType.APPLICATION_OCTET_STREAM); HttpEntity<String> entity = new HttpEntity<String>(headers); ResponseEntity<byte[]> restTemplateResponse = restTemplate.exchange(uri, HttpMethod.GET, entity, byte[].class); |
MediaType.APPLICATION_OCTET_STREAM 은
표준으로 정의되어있지 않은 파일인 경우 지정하는 타입이다.
octet stream이 8비트로 된 데이터이니, 순수한 바이너리 데이터로 받아온다는 의미이다.
받는 것은 byte 배열로 받으면 된다.
이제 바이너리 파일을 받았으니,
어드민 페이지에서 사용자가 txt 파일로 다운로드 받게 할 차례다.
@RequestMapping("/get_file") public void getFile(HttpServletRequest request, HttpServletResponse response) { // server to server call // get binary file response.setContentType("text/plain"); response.setHeader("Content-Disposition", "attachment;filename=result.txt");
ServletOutputStream sos = response.getOutputStream(); IOUtils.write(restTemplateResponse.getBody(), sos); } |
text 파일이기 때문에 컨텐츠타입을 text/plain 으로 정의했다.
다른 파일이면 다른 컨텐츠타입을 명시한다.
가장 핵심인 setHeader에 "Content-Disposition", "attachment;filename=result.txt" 를 써준다.
Content-Disposition 은 브라우저에서 다운로드 창을 띄우는 역할을 하며,
뒤에 파라미터를 통해 파일 이름과 확장자를 지정한다.
그다음은 스트림 파일을 통해 write 해주면 끝..
처음에는 @ResponseBody를 붙이고 File을 리턴하고
메시지 컨버터 설정을 해야하나 했는데
저렇게 response에 타입 지정하니까 잘 된다.
바이너리라 그런지 한글도 깨지지 않고 잘 나온다 후훗
'개발 > Spring' 카테고리의 다른 글
"Building UI model" has encountered a problem. (1) | 2021.01.11 |
---|---|
@PathVariable 여러개 주소 못찾는 경우 (0) | 2016.09.29 |
Springframework, Ajax에서 한글이 물음표로 나오는 현상 (25) | 2015.04.03 |
[에러] type parameters of T cannot be determined;,.,, (1) | 2014.11.06 |
[Spring] Service 객체에서 초기화 하는 init 메소드 만들기 (2) | 2014.05.15 |