Kim VamPa

[Spring][쇼핑몰 프로젝트][26] 업로드 이미지 삭제 - 1 본문

스프링 프레임워크/쇼핑몰 프로젝트

[Spring][쇼핑몰 프로젝트][26] 업로드 이미지 삭제 - 1

Kim VamPa 2021. 5. 31. 16:48
728x90
반응형
프로젝트 Github : https://github.com/sjinjin7/Blog_Project
프로젝트 포스팅 색인(index) : https://kimvampa.tistory.com/188

목표

이미지 삭제 기능 구현

 최종 목표는 이미지 삭제 기능 구현이며 이번 포스팅에서는 서버 단계에서 이미지 삭제를 처리하는 url 매핑 메서드 구현을 목표로 합니다. 

 

 

순서

1. 방향

2. 메서드 작성

 

 

1. 방향

 이미지 삭제 기능을 수행하는 url 매핑 메서드를 작성할 것입니다. 이미지 파일 삭제를 위해 가장 핵심이 되는 메서드는 File 클래스의 delete()입니다. 

 

그림 1-1 java api 공시문서(File)

 

 이 메서드를 사용하기 위해선 File 클래스를 인스턴스화 하여 사용해야 합니다. 삭제될 파일을 대상으로 하는 File 객체를 생성하기 위해선 생성자에  대상 파일의 경로인 문자열 데이터를 파라미터로 부여해야 합니다. 따라서 삭제할 대상의 파일의 경로가 필요로 하기 때문에 url 매핑 메서드의 파라미터로 파일경로(fileName)을 부여할 것입니다.

 

 파일 삭제를 수행하는 url 매핑 메서드는 뷰에서 비동기 방식으로 요청을 하고 수행 결과를 요청하기 때문에 비동기 요청을 수행하도록 작성해주어야 합니다. 저번 포스팅에서도 언급을 하였지만 선택지는 2가지가 있습니다. 첫 번째는 ResponseBody 어노테이션입니다. 두 번째는 ResponseEntity 객체를 반환 타입으로 사용하는 것입니다. 저는 코드의 수행 결과에 따라 다른 상태 코드를 전송하기 위해서 ResponseEntity를 사용할 것입니다.

 

 

2. 메서드 작성

 이미지 파일 삭제를 수행하는 url 매핑 메서드는 AdminController.java 에 작성을 하겠습니다. 이미지 파일 삭제를 수행하는 사람은 관리자만이 할 수 있도록 하기 위함입니다.

 

 AdminController.java에 아래의 코드를 작성합니다.

 

	/* 이미지 파일 삭제 */
	@PostMapping("/deleteFile")
	public ResponseEntity<String> deleteFile(String fileName){
		
		logger.info("deleteFile........" + fileName);
		
	}

 

 전달 방식은 POST 방식으로 하였으며 url은 'deleteFile'로 작성을 하였습니다. 앞서 순서 1에서 말하였듯이 파일의 경로 및 이름을 전달받기 위해 String 타입의 fileName 변수 파라미터로 부여하였으며 반환 타입은 ResponseEntity으로 하였고 HTTP Body에 String 데이터를 추가하기 위해 타입 매개 변수로서 String을 부여하였습니다.

 

 url 매핑 메서드의 구현 부에 File 타입의 참조 변수를 선언하고 null로 초기화해줍니다. 

 

		File file = null;

 

그림 2-1

 

 

2.1 try-catch 

 

 앞으로 작성할 메서드들이 URLDecoder.decode(), File.delete()가 있는데 두 개 모두 예외를 발생시킬 가능성이 큰 메서드입니다. 따라서 try-catch문을 먼저 작성해주겠습니다. ( 두 개의 메서드가 일으킬 수 있는 예외들이 각각 다르지만 현재 기능 구현이 목표이기 때문에 모든 예외를 처리해주는 Exception을 catch의 파라미터로 부여해주겠습니다.)

 

		try {
			
		} catch(Exception e) {
			
			e.printStackTrace();
			
		}

 

 예외가 발생했다는 의미는 이미지 파일 삭제 요청을 정상적으로 처리하지 못하였다는 의미이기 때문에 실패하였다는 것을 알리도록 return문을 catch 구현부에 작성하였습니다.

 

		try {
			
		} catch(Exception e) {
			
			e.printStackTrace();
			
			return new ResponseEntity<String>("fail", HttpStatus.NOT_IMPLEMENTED);
			
		}

 

 

2.2 URLDecoder.decode 적용 및 썸네일 파일 삭제

 

 다음 포스팅에서 진행할 뷰(view) 단계에서의 작업에서는 업로드 시 출력되는 미리 보기 이미지의 우측 상단의 x 표시의 <div> 태그를 사용자가 클릭을 하면 서버에 삭제를 요청하도록 구현을 할 것입니다. 이 과정에서 파일 이름 및 경로에 대한 데이터를 보내도록 구성을 할 것인데, 해당 데이터는 저번 포스팅에서 진행하였던 encodeURIComponent() 메서드를 통해 UTF-8로 인코딩 된 데이터 그대로 전송되도록 작업을 할 것입니다. (인코딩 된 경로의 파일은 썸네일 이미지 파일입니다.)

 

 문제는 File 객체를 생성하기 위해 파라미터로 부여할 문자열(String) 데이터는 슬래시(/) 혹은 역슬래시(\)를 구분자로 하는 경로여야 하는데, 해당 구분자들이 UTF-8로 인코딩 되었기 때문에 구분자들(한글 이름 문자 포함)이 "%5", "%2F" 따위의 문자로 변경되어 있기 때문에 fileName 변수에 담긴 데이터 자체만으로는 삭제 대상인 파일을 지정해 줄 수 없습니다. 

 

 따라서 fileName에 담긴 데이터를 디코딩(Decoding) 해주어야 하는데 이를 위해 사용할 메서드가 URL Decoder 클래스의 decode() 메서드입니다.

 

 

 decode() 메서드는 static 메서드 이기 때문에 인스턴스화 없이 사용이 가능합니다. 첫 번째 파라미터는 디코딩할 대상 문자열 데이터입니다. 두 번째 파라미터는 대상 문자열 데이터가 어떠한 타입으로 인코딩 되었는지에 대한 정보를 부여합니다. 리턴 타입은 디코딩된 문자열(String) 데이터입니다.

 

 

 

 삭제할 파일을 대상으로 하는 File 클래스를 인스턴스화 하여 앞서 선언한 file 참조 변수가 참조하도록 합니다.

 

		try {
			
			file = new File("c:\\upload\\" + URLDecoder.decode(fileName, "UTF-8"));
			
			
		} catch(Exception e) {
			
			e.printStackTrace();
			
			return new ResponseEntity<String>("fail", HttpStatus.NOT_IMPLEMENTED);
			
		}

 

 delete() 메서들를 호출하여 대상 파일을 삭제하도록 코드를 작성합니다.

 

		try {
			
			file = new File("c:\\upload\\" + URLDecoder.decode(fileName, "UTF-8"));
			
			file.delete();
			
			
		} catch(Exception e) {
			
			e.printStackTrace();
			
			return new ResponseEntity<String>("fail", HttpStatus.NOT_IMPLEMENTED);
			
		}

 

 

 

2.3 원본 파일 삭제

 

 우리는 업로드 당시 이미지 원본 파일과 썸네일 이미지를 생성 및 저장하였습니다. 따라서 앞서 썸네일 이미지를 삭제하였기 때문에 이번엔 원본 파일을 삭제해주겠습니다. 원본 파일 대상 File 객체를 생성해주기 위해서 파일 경로 문자열 데이터가 필요로 합니다. 

 

 앞서 썸네일 파일의 File 객체를 생성했을 때와 같이 "c:\\upload\\"와 fileName 데이터를 합친 후 String 클래스의 replace를 통해 "s_" 문자를 없애주어도 되지만, 이미 풀 경로의 정보를 가지고 있는 File 객체(file) 존재하기 때문에 해당 객체를 활용하겠습니다. File 클래스의 getAbsolutePath() 메서드를 사용할 것인데 해당 메서드를 호출하면 대상 File 객체의 경로를 문자열(String) 타입의 데이터로 반환을 해줍니다.

 

 String 타입의 originFileName 변수를 선언한 후  원본 파일 경로를 문자열(String) 데이터로 초기화합니다. 추가적으로 원본 파일 경로가 정상적인 값을 가지는지 확인을 하기 위해서 logger() 메서드를 작성하였습니다.

 

※ String 클래스의 replace() 메서드는 첫 번째 인자로 부여한 문자열 데이터를 찾아서, 두 번째 인자로 부여한 문자열 데이터로 치환해줍니다.

 

		try {
			/* 썸네일 파일 삭제 */
			file = new File("c:\\upload\\" + URLDecoder.decode(fileName, "UTF-8"));
			
			file.delete();
			
			/* 원본 파일 삭제 */
			String originFileName = file.getAbsolutePath().replace("s_", "");
			
			logger.info("originFileName : " + originFileName);
			
			
		} catch(Exception e) {
			
			e.printStackTrace();
			
			return new ResponseEntity<String>("fail", HttpStatus.NOT_IMPLEMENTED);
			
		}

 

 본 파일을 대상으로 하는 File 객체를 생성 후 이를 기존에 선언하고 사용하였던 file 참조 변수가 참조하도록 합니다. 썸네일 이미지 삭제와 동일하게 원본 파일 이미지를 삭제하도록 delete() 메서드를 호출합니다.

 

		try {
			/* 썸네일 파일 삭제 */
			file = new File("c:\\upload\\" + URLDecoder.decode(fileName, "UTF-8"));
			
			file.delete();
			
			/* 원본 파일 삭제 */
			String originFileName = file.getAbsolutePath().replace("s_", "");
			
			logger.info("originFileName : " + originFileName);
			
			file = new File(originFileName);
			
			file.delete();
			
			
		} catch(Exception e) {
			
			e.printStackTrace();
			
			return new ResponseEntity<String>("fail", HttpStatus.NOT_IMPLEMENTED);
			
		}

 

그림 3-2

 

 

2.4 리턴

 

 try문이 예외가 발생하지 않은 것은 정상적으로 삭제 작업을 수행했다는 것이기 때문에 성공 상태 코드와 함께 성공과 관련된 문자열을 뷰로 전송해주도록 return 문을 작성합니다.

 

return new ResponseEntity<String>("success", HttpStatus.OK);

 

그림 3-3

 

 

REFERENCE

 

 

 

DATE

  • 2020.05.31
728x90
반응형
Comments