Kim VamPa

[Spring][쇼핑몰 프로젝트][24] 상품 이미지 업로드(서버 단계 이미지 파일 체크) - 7 본문

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

[Spring][쇼핑몰 프로젝트][24] 상품 이미지 업로드(서버 단계 이미지 파일 체크) - 7

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

목표

서버 단계 이미지 파일 체크, 뷰에 에러 반환

  이미 뷰에서 이미지 파일을 서버로 전송하기 전에 사용자가 업로드를 위해 선택한 파일이 이미지 파일인지 체크를 하도록 코드를 작성하였습니다. 하지만 엄연히 뷰 단계에서의 파일 체크일 뿐, 만약 이미지 파일 체크 코드가 작동을 하지 않거나 다른 경로를 통해 업로드 url 매핑 메서드를 호출할 경우 이미지가 아닌 파일도 업로드될 가능성이 있습니다.

 

 따라서 좀 더 확실히 이미지 파일만 처리를 보장하는 메서드가 되도록 하기 위해서 업로드를 수행하는 url 매핑 메서드에도 전달 받은 파일이 이미지 파일인지 체크를 하는 코드를 추가해줄 것입니다. 파일을 체크하여 파일이 아닐 경우 에러 상태 코드를 전송을 하여, 뷰에서 그에 따른 경고창이 출력되도록 구현할 것입니다.

 

 

 

순서

1. 전체적 방향

2. MIME TYPE 데이터 얻기

3. MIME TYPE 체크 및 데이터 반환

4. 뷰(View) 처리

5. 테스트

 

 

 

1. 전체적 방향

 전달 받은 파일이 이미지 인지 아닌지 체크를 하기 위해서 파일의 MIME TYPE 속성을 활용할 것입니다. MIMIE TYPE 이란 쉽게 말해 파일이 어떠한 종류의 파일인지에 대한 정보가 담긴 라벨(Label)이라고 보시면 됩니다. Java에선 파일의 Mime Type을 반환해주는 메서드를 제공하고 있는데 nio 패키지 Files 클래스의 probeContentType() 메서드입니다.

 

 probeContentType() 메서드를 호출하여 반환받은 Mime Type에 대한 데이터가 image 인지 체크를 하여 image인 경우 업로드 코드가 그대로 실행이 되도록 할 것입니다. image가 아닌 경우 업로드에 관한 코드가 실행이 되지 않고 상태 코드 400을 뷰에 반환하도록 할 것입니다. 

 

 뷰에서는 ajax의 error 속성을 추가하여 상태코드 400을 전달받았을 때 실행이 되는 콜백 함수를 속성 값으로 부여하여 잘못된 형식의 파일이라는 경고 문구를 뜨도록 할 것입니다.

 

 

2. MIME TYPE 체크

 파일 유형을 체크하는 코드는 업로드를 수행하는 코드가 실행이 되기 전에 실행이 되어야 하기 때문에 업로드 url 매핑 메서드 구현부의 최상단에 코드를 작성할 것입니다.

 

그림 1-1

 

 전달받은 모든 파일(uploadfile)의 유형을 체크해야 하기 때문에 for문을 작성해줍니다.

 

		/* 이미지 파일 체크 */
		for(MultipartFile multipartFile: uploadFile) {
			
		}

 

 먼저 전달받은 파일(uploadfile)을 File 객체로 만들어주고 File 참조 변수에 대입합니다.

 

		/* 이미지 파일 체크 */
		for(MultipartFile multipartFile: uploadFile) {
			
			File checkfile = new File(multipartFile.getOriginalFilename());
			
		}

 

 MIME TYPE을 저장할 String 타입의 type 변수를 선언하고 null로 초기화합니다.

 

		/* 이미지 파일 체크 */
		for(MultipartFile multipartFile: uploadFile) {
			
			File checkfile = new File(multipartFile.getOriginalFilename());
			String type = null;
			
		}

 

 Files의 probeContetype() 메서드를 호출하여 반환하는 MIME TYPE 데이터를 type 변수에 대입합니다. 

 

		/* 이미지 파일 체크 */
		for(MultipartFile multipartFile: uploadFile) {
			
			File checkfile = new File(multipartFile.getOriginalFilename());
			String type = null;
			
			type = Files.probeContentType(checkfile.toPath());
			
		}

 

그림 1-2 File API 공식 문서

 

 probeContentType은 파라미터로 전달받은 파일의 MIME TYPE을 문자열(Stirng) 반환해주는 메서드입니다. 파라미터로는 Path 객체를 전달받아야 합니다. 따라서 MIME TYPE 확인 대상이자 File 객체인 checkfile을 Path 객체로 만들어 주어야 하는데, 이를 위해 File 클래스의 toPath() 메서드를 사용하였습니다.

 

 

 추가적으로 probeContetype() 메서드의 경우 IOException 예외를 일으 킬 가능성이 크므로 컴파일러에서 try/catch 문을 사용하라는 경고가 뜹니다. probeContentType() 메서드를 try/catch 문으로 감싸줍니다. 추가적으로 반환받은 MIME TYPE을 확인하기 위해 logger() 메서드를 추가해주었습니다.

 

		/* 이미지 파일 체크 */
		for(MultipartFile multipartFile: uploadFile) {
			
			File checkfile = new File(multipartFile.getOriginalFilename());
			String type = null;
			
			try {
				type = Files.probeContentType(checkfile.toPath());
				logger.info("MIME TYPE : " + type);
			} catch (IOException e) {
				e.printStackTrace();
			}
			
		}

 

3. MIME TYPE 체크 및 데이터 반환

 

전달받은 파일이 어떠한 MIME TYPE을 가졌는지에 대한 데이터를 얻었습니다. 이제 이를 image인지 아닌지 체크를 해야 합니다. MIME TYPE이 이미지일 경우 MIME TYPE 값은 아래와 같을 것입니다. (MIME TYPE에 대한 자세한 정보와 그 종류에 대해 알고 싶으시다면 https://developer.mozilla.org/ko/docs/Web/HTTP/Basics_of_HTTP/MIME_types 을 참고하시면 됩니다.)

 


image/gifimage/pngimage/jpegimage/bmpimage/webp

 

 MIME TYPE이 image 인 경우 보시다시피 첫 단어가 image 인 것을 알 수 있습니다. 따라서 첫 단어가 image 인지 아닌지를 통해서 image 파일 임을 판단하겠습니다. 이를 위해 String 클래스의 startsWith() 메서드를 사용할 것입니다. startsWiath() 메서드는 String 타입의 데이터를 파라미터로 전달받는데, 체크 대상인 Stirng 데이터가 메서드의 파라미터로 전달받은 문자로 시작할 경우 true를 그렇지 않을 경우 false를 반환합니다.

 

 MIME TYPE이 image가 아닌 경우 구현부가 실행이 되는 if문을 아래와 같이 작성했습니다.

 

		/* 이미지 파일 체크 */
		for(MultipartFile multipartFile: uploadFile) {
			
			File checkfile = new File(multipartFile.getOriginalFilename());
			String type = null;
			
			try {
				type = Files.probeContentType(checkfile.toPath());
				logger.info("MIME TYPE : " + type);
			} catch (IOException e) {
				e.printStackTrace();
			}
			
			if(!type.startsWith("image")) {
				
			}
			
		}

 

 구현부가 실행이 되었다는 것은 image가 아니라는 것이기 때문에 메서드가 끝나도록 할 것입니다. 전달받은 파일이 image가 아니기 때문에 파일에 대한 정보를 뷰에 전달해줄 필요는 없습니다. 하지만 명령이 잘못되었음을 전달하기 위해 response의 상태코드(status)를 400으로 반환 할 것입니다.

 

 먼저 전달 해줄 파일의 정보는 없지만 반환 타입이 ResponseEntity<List<AttachImageVO>>이기 때문에 ResponseEntity 객체에 첨부해줄 값이 null인 List <AttachImageVO> 타입의 참조 변수를 선언하였습니다. 

 

		/* 이미지 파일 체크 */
		for(MultipartFile multipartFile: uploadFile) {
			
			File checkfile = new File(multipartFile.getOriginalFilename());
			String type = null;
			
			try {
				type = Files.probeContentType(checkfile.toPath());
				logger.info("MIME TYPE : " + type);
			} catch (IOException e) {
				e.printStackTrace();
			}
			
			if(!type.startsWith("image")) {
				
				List<AttachImageVO> list = null;
				
			}
			
		}// for

 

 상태 코드가 400인 ResponseEntity 객체를 인스턴스화 하여 이를 반환해주는 코드를 아래와 같이 작성합니다. ( ResponseEntity의 생성자와 상태 코드에 따른 HttpStatus의 상수 값들을 알고 싶으시다면 ResponseEntity API 문서, HttpStatus API 문서를 참고하시면 됩니다.)

 

 

		/* 이미지 파일 체크 */
		for(MultipartFile multipartFile: uploadFile) {
			
			File checkfile = new File(multipartFile.getOriginalFilename());
			String type = null;
			
			try {
				type = Files.probeContentType(checkfile.toPath());
				logger.info("MIME TYPE : " + type);
			} catch (IOException e) {
				e.printStackTrace();
			}
			
			if(!type.startsWith("image")) {
				
				List<AttachImageVO> list = null;
				return new ResponseEntity<>(list, HttpStatus.BAD_REQUEST);
				
			}
			
		}// for

 

그림 3-1

 

4. 뷰(View) 처리

 잘못된 파일이 전달받았음을 알리는 상태 코드가 400인 response를 전달 받았을때 이를 처리 해줄 코드를 추가해주어야 합니다. 현재 작성되진 ajax에 상태코드가 200 인 경우 응답을 하는 success 속성만 추가되어져 있습니다. 따라서 에러 상태코드 일 때 응답을 하는 error 속성을 추가해주고 속성 값으로 콜백 함수를 부여합니다.

 

		,
	    	error : function(result){
	    		
	    	}

 

그림 4-1

 

  콜백 함수에 잘못된 파일이 선택되었음을 알리는 문구는 경고창을 출력하도록 코드를 작성하였습니다.

 

		
		$.ajax({
			url: '/admin/uploadAjaxAction',
	    	processData : false,
	    	contentType : false,
	    	data : formData,
	    	type : 'POST',
	    	dataType : 'json',
	    	success : function(result){
	    		console.log(result);
	    	},
	    	error : function(result){
	    		alert("이미지 파일이 아닙니다.");
	    	}
		});	
        

 

그림 4-2

 

 

5. 테스트

 테스트를 위해서 이미지가 아닌 파일을 전송해야 하기 때문에 뷰(View)에서 이미지 파일을 체크하는 JS코드를 잠시 주석 처리하여 테스트합니다.

 

그림 5-1

 

그림 5-2

 

그림 5-3

 

그림 5-4

 

 

REFERENCE

DATE

  • 2020.05.19
728x90
반응형
Comments