첨부파일의 업로드가 처리되는 과정도 복잡하지만, 이를 사용자가 사용하는 과정 역시 신경 써야한다.
브라우저에 보이는 첨부파일은
1. 이미지 종류, 2. 일반파일
로 구분되므로 사용자의 첨부파일관련된 행위도 종류에 따라 다르게 처리 되어야 한다.
만약 이미지인 경우에는 썸넬 이미지를 클릭했을 때 화면에 크게 원본 파일을 보여주는 형태로 처리되어야 한다.
이 경우 브라우저에서 새로운<div>태그를 생성해서 처리하는 방식을 이용한다.
이걸 light-box라고 한다.
light-box는 제이쿼리를 이용하는 많은 플로그인들이 있다. 이를 이용하거나 직접 구현할 수있다.
한번 직접 구현해보겠다.
첨부파일이 이미지가 아닌 경우 , 기본값은 다운로드로 설정하겠다.
첨부파일의 다운로드
이미지를 처리하기 전 간단한 첨부파일의 다운로드 부터 처리하도록 해보겠다.
이미지를 띄우는 것과 달리 MIME타입이 고정되기 때문에 메서드는 아래와 같이 시작하게 된다.
@GetMapping(value = "/download", produces = MediaType.APPLICATION_OCTET_STREAM_VALUE)
@ResponseBody
public ResponseEntity<Resource> downloadFile(String fileName) {
log.info("download file: " + fileName);
Resource resource = new FileSystemResource("C:\\programing\\upload\\" + fileName);
log.info("resource: " + resource);
return null;
}
REsponseEntity<>의 타입은 byte[]등을 사용할 수 있으나, 이번 예제에서는 org.springframework.core.io.Resource
타입을 이용해서 좀 더 간단히 처리하도록 한다.
테스트를 위해서 해당 다운로드 경로에 영문 파일을 하나 놓고
/download?fileName=파일이름 형태로 호출한다.
http://localhost:8080/download?fileName=logo.png
브라우저에는 아무반응이없지만, 서버에는 로그가 기록된다.
서버에 파일이 성장석으로 인식되었다는 것이 확인되면 ResponsEntity<>를 처리한다.
@GetMapping(value = "/download", produces = MediaType.APPLICATION_OCTET_STREAM_VALUE)
@ResponseBody
public ResponseEntity<Resource> downloadFile(String fileName) {
log.info("download file: " + fileName);
Resource resource = new FileSystemResource("C:\\programing\\upload\\" + fileName);
log.info("resource: " + resource);
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);
}
MIME타입은 다운로드 할수있는 application/octet-stream으로 지정하고, 다운로드 시 저장되는 이름은 Content-Disposition을 이용해서 지정한다.
그리고 문자열 처리는 UTF-8 , ISO-8859-1는 한글이 꺠지는 것을 방지하기 위한것이다.
http://localhost:8080/download?fileName=logo.png 를 다시 실행해보자
그럼 다운로드 확인 버튼이 나온다!!
만약 브라우저를 Edgo/IE 를쓴다면 아래를 펼쳐서 해결하도록하자. 코드만 작성해놓겠다.
IE나 엣지를 같이 서비스해야한다면? 지금 다운로드 받을때 한글깨짐이 일어난다.
@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("c:\\upload\\" + fileName);
if(resource.exists() == false) {
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
}
String resourceName = resource.getFilename();
HttpHeaders headers = new HttpHeaders();
try {
boolean checkIE = (userAgent.indexOf("MSIE") > -1 ||
userAgent.indexOf("Trident") > -1);
String downloadName = null;
if (checkIE) {
downloadName = URLEncoder.encode(resourceName, "UTF8").replaceAll("\\+", "
");
} else {
downloadName = new String(resourceName.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);
}
로 처리하면 파일이 정상적으로 뜰수있다. 참고정도만 넘어가자..
업로드된 후 다운로드 처리
다운로드 자체에 대한 처리는 완료되었다.
이제 /upload 화면에서 업로드된 후 파일이미지를 클릭한 경우 다운로드가 될 수 있도록 처리하자.
기존의 showUploadedFile() 함수를 수정하자
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+ "/thumb_"+obj.uuid +"_"+obj.fileName);
str += "<li><a href=\"javascript:showImage(\'"+originPath+"\')\"><img src='/display?fileName="+fileCallPath+"'></a><li>";
}
});
uploadResult.append(str);
}
수정된 부분은 파일을 클릭하면 다운로드에 필요한 경로와 UUID붙은 파일 이름을 이용해 다운로드가 가능하도록
<a>태그를 이용해서 '/download?fileName=****'부분을 추가했다.
브라우저에서는 <img>태그를 클릭하게 되면 자동으로 다운로드가 되는 것을 확인할 수 있다.
물론 이미지말고 이미지가 아닌 다른 파일확장자 일경우에!
다운로드가 정상적으로 이루어지는 것을 확인하였다면 마지막으로 서버에서 파일이름에 UUID가 붙은 부분을 제거하고 순수하게 다운로드 되는 파일의 이름으로 저장 될 수 있도록한다.
@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("C:\\programing\\upload\\" + fileName);
if (resource.exists() == false) {
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
}
String resourceName = resource.getFilename();
// remove UUID
String resourceOriginalName = resourceName.substring(resourceName.indexOf("_") + 1);
HttpHeaders headers = new HttpHeaders();
try {
boolean checkIE = (userAgent.indexOf("MSIE") > -1 || userAgent.indexOf("Trident") > -1);
String downloadName = null;
if (checkIE) {
downloadName = URLEncoder.encode(resourceOriginalName, "UTF8").replaceAll("\\+", " ");
} 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);
}
수정된 부분은 resourceOriginalName을 생성해서 UUID 부분을 잘라낸 상태의 파일이름으로 저장하도록 했다.
브라우저에서는 순수한 파일 이름으로 다운로드 될 것이다.
String resourceOriginalName = resourceName.substring(resourceName.indexOf("_") + 1);
이제 깔끔하게 test.txt만 나오는것을 알수있다!
다음에는 원본이미지와 첨부파일에서 제거하는 것을 실습해보겠다.
'Spring공부 > 3-파일업로드' 카테고리의 다른 글
파일업로드(6)-첨부파일삭제 (0) | 2021.10.14 |
---|---|
파일업로드(5)-원본 이미지 보여주기 (0) | 2021.10.14 |
파일업로드(3)-업로드데이터변환 (0) | 2021.10.13 |
파일업로드(2) (0) | 2021.10.13 |
파일 업로드(1) (0) | 2021.10.12 |
댓글