코딩항해기

[JSP] 입력받은 이미지 파일 저장하기 본문

JSP

[JSP] 입력받은 이미지 파일 저장하기

miniBcake 2024. 8. 27. 15:26

 

 

 

 

[JSP] DB에서 이미지 파일 경로 받아서 화면에 띄우기

예를 들어 마이페이지에서 특정 member의 프로필 이미지를 출력하는 기능을 구현하려고 한다.하지만 DB에 바로 이미지 파일을 저장할 수 없다는 점에서 해당 기능을 기존 id, 이름 출력처럼 진행하

minibcake.tistory.com

 

 

지난 게시물에는 이미 저장되어있는 이미지 파일을 화면에 출력하는 방법에 대해 정리했다.

이번에는 반대로 화면에서 입력받은 이미지를 DB와 서버에 저장하는 방법에 대해 정리해보겠다.

 

V

View(이하 V)에서는 이미지를 입력받을 태그를 만들어야한다. 이미지도 파일의 일종이므로, input[type="file"]을 사용하여 이미지를 사용자에게 입력 받을 수 있다. 전달받은 이미지 데이터는 파일급 데이터이기 때문에 바로 전송할 수는 없고, 인코딩(enc)과정을 거쳐야한다. 관련 jar파일을 buildpath 해 준 뒤에 form 태그에 인코딩 관련 속성을 넣어준다.

enctype=”multipart/form-data”

 

그럼 이제 인코딩 속성에 따라 전송 버튼을 누르면 img파일이 Part타입의 값으로 전달될 것이다.

 

C

Controller(이하 C)에서는 전달받은 이미지 값을 Part타입으로 받아주면된다. 전달 받은 이미지가 없을 경우, 미리 만들어둔 기본 이미지로 저장할 예정이기 때문에 전달받은 이미지의 값이 있다면 해당 값으로, 아니라면 상단에 미리 선언해둔 값을 Model(이하M)에게 전달하여 DB에 넣어주면된다.

 

일반적인 데이터라면 Model에 값을 전달한 순간 저장이 끝났겠지만 이미지(파일)타입은 저장할 수 없어 경로만 보내기 때문에, 서버에 입력받은 이미지(파일)을 따로 저장해줘야한다.

 

 

 

[JAVA] 파일 입출력

자바 입출력 스트림 특징자바에서는 입출력이 동시에 진행되는 것이 아니라 독립적으로 한 가지 기능만 동작하기 때문에 데이터를 교환하기 위해서는 입력 스트림과 출력 스트림이 따로 필요

minibcake.tistory.com

 

이때는 파일 입출력을 활용하여 이미지를 지정된 경로의 위치에 저장해주게 되며, 이 때 파일의 이름이 동일한 파일이 있다면 덮어씌우지게 되므로 최대한 이미지 이름이 겹치지 않도록 해야한다. 겹치지 않게 UUID 같은 식별자를 사용하는 방법이 있으며, 별도로 직접 만든 알고리즘을 통해 이미지 이름을 작성해도 된다.

 

UUID
Universally Unique Identifier
128-bit의 고유 식별자로 다른 고유 ID 생성 방법과 다르게 UUID는 중앙 시스템에 등록하고 발급하는 과정이 없어서 상대적으로 더 빠르고 간단하게 만들 수 있다는 장점이 있다.

 

프로필 이미지는 member당 1개만 가지는 이미지고, 새롭게 변경할 경우 이전의 이미지를 저장할 필요는 없기 때문에 파일 명을 mid(member의 PK값)으로 설정해줘도 예제에는 문제가 생기지 않을 것으로 보인다.

 

		imagepath=Paths.get(file.getSubmittedFileName()).getFileName().toString(); 
        	//파일 이름을 String타입으로 추출
		String fileName = mid+imagepath.substring(imagepath.lastIndexOf(".")); 
       	 	//mid(member의 pk값)에 추출한 파일 이름에서 확장자만 추출하여 합침
		
		if(file != null) { 
        	// 사용자가 이미지를 등록했다면,
			System.out.println("로그 : 이미지 업로드 시작");

			// 이미지 업로드 로직
			File uploadFile=new File(new File(PATH), fileName); 
            		//기존 정의해둔 경로에 mid(member의 pk값)으로 저장, 별도로 제작한 파일 이름으로 설정
			try (InputStream input = file.getInputStream(); //파일의 입력스트림을 열음
					FileOutputStream output = new FileOutputStream(uploadFile)) {
				byte[] buffer = new byte[1024];
				int length;
				while ((length = input.read(buffer)) > 0) {//입력스트림에서 읽어온 값이 있다면
					output.write(buffer, 0, length);//출력스트림에 복사
				}
			}catch(Exception e) {
				e.printStackTrace();
			}

			memberDTO.setImagepath(fileName);//DB에도 서버에 저장된 이름과 동일한 이름으로 저장

			System.out.println("로그 : 이미지 업로드 끝");
		}

 

이미지 저장 방식은 Spring에서 진행되는 방식을 템플릿으로 가져와 사용했다.

 

여기서 추가로 주의할 점은 파일을 인코딩할 때 외부라이브러리를 사용하고 있으므로 해당 인코딩된 데이터가 지나는 곳마다 상단에 어노테이션으로 표기해주어야한다. 이때 사용되는 어노테이션은 MultipartConfig이다.

@MultipartConfig

 

M

Model(이하 M)은 C로부터 전달받은 경로를 DB에 저장하면 된다.