Spring + Ajax 파일 다운로드

첨부파일 다운로드

UploadController.java

	@GetMapping(value = "/download", 
				produces = MediaType.APPLICATION_OCTET_STREAM_VALUE)
	@ResponseBody
	public ResponseEntity<Resource> downloadFile(String fileName) {

		Resource resource = new FileSystemResource("D:\\upload\\" + fileName);
		String resourceName = resource.getFilename();

		HttpHeaders headers = new HttpHeaders();
		try {
			headers.add("Content-Disposition",
					"attachment; filename=" + new String(resourceName.getBytes("UTF-8"), "ISO-8859-1"));
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		return new ResponseEntity<Resource>(resource, headers, HttpStatus.OK);
	}
  • /download?fileName=XXX'와 같이 호출 시 파일 다운로드 한다.
  • MIME 타입은 다운로드 할 수 있는 'application/octet-stream'으로 지정한다.
  • 다운로드시 저장되는 이름은 'Content-Disposition'을 이용해서 지정한다.
    파일 이름에 한글인 경우 저장할 때 깨지는 문제를 막을 수 있다.

  • ResponseEntity<Resource>
    • ResponseEntity<> 타입은 byte[] 등을 사용할 수 있지만, Resource를 이용해 좀 더 간단히 처리가 가능하다.

 

UploadAjax.jsp

		function showUploadedFile(uploadResultArr) {

			var str = "";

			$(uploadResultArr).each(function(i, obj){
		        
		        if(!obj.image){
		          	var fileCallPath =  encodeURIComponent( obj.uploadPath+"/"+ obj.uuid +"_"+obj.fileName);
		          	str += "<li><a href='/download?fileName="+fileCallPath+"'>" 
		        		  +"<img src='/resources/img/attach.png'>"+obj.fileName+"</a></li>"
		        }else{
		          	var fileCallPath =  encodeURIComponent( obj.uploadPath+ "/s_"+obj.uuid +"_"+obj.fileName);
		          	str += "<li><img src='/display?fileName="+fileCallPath+"'><li>";
		        }
		    });
			uploadResult.append(str);
		}
  • 이미지 파일인 경우 이미지가 보이도록 / 일반 파일인 경우 attach.png 파일이 보이게 설정
  • 이미지를 클릭하였을 때 첨부 파일이 다운받아지도록 설정

 

 

하지만 문제 두 가지!!

 

  • 아직 까지 fileCallPath는 UUID가 붙은 파일이름으로 순수한 파일이름이 아니기 때문에 이를 처리하는 작업이 필요하다.
  • 크롬이 아니라 IE(인터넷 익스플로어), Edge에서는 한글 파일이 제대로 다운받아지지 않는 문제가 있다.

 

UploadController.java

	@GetMapping(value = "/download", 
				produces = MediaType.APPLICATION_OCTET_STREAM_VALUE)
	@ResponseBody
	public ResponseEntity<Resource> downloadFile(@RequestHeader("User-Agent") String userAgent, String fileName) {

		Resource resource = new FileSystemResource("D:\\upload\\" + fileName);

		if (resource.exists() == false) {
			return new ResponseEntity<Resource>(HttpStatus.NOT_FOUND);
		}

		String resourceName = resource.getFilename();
		
		// remove UUID
		String resourceOriginalName = resourceName.substring(resourceName.indexOf("_") + 1);

		HttpHeaders headers = new HttpHeaders();
		try {

			String downloadName = null;
			
			// IE(Internet Explorer
			if (userAgent.contains("Trident")) {
				downloadName = URLEncoder.encode(resourceOriginalName, "UTF-8").replaceAll("\\+", " ");
			} 
			// Edge
			else if (userAgent.contains("Edge")) {
				downloadName = URLEncoder.encode(resourceOriginalName, "UTF-8");
			}
			else {
				downloadName = new String(resourceOriginalName.getBytes("UTF-8"), "ISO-8859-1");
			}


			headers.add("Content-Disposition", "attachment; filename=" + downloadName);

		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}

		return new ResponseEntity<Resource>(resource, headers, HttpStatus.OK);
	}