이미지 파일 업로드하기(insert-image)

2024. 6. 21. 12:56JSP+Spring Boot

이미지를 form 태그에 넣어서 업로드를 진행할 때는 entype을 작성 
enctype(encoding type) : 어떤 파일을 전송할 때 데이터 타입이 무엇인지 체크
    - 이미지 파일을 post로 업로드 하기 위해서는 multipart/form-data를 작성해서 전달하는 것이 안전

    application/x-www-form-urlencoded : 기본 값 = 글자 데이터만 전달
                                        name=value 값이 있어서 name로 전송

    multipart/form-data : 비디오, 이미지와 같은 데이터도 같이 전달

    text/plain : 변환(인코딩)하지 않고 그대로 전송. 버그 찾는 데 사용

 

사진을 저장하고 불러올 때 sql 컬럼 자료형으로 varchar2를 사용할 수 있고 이미지 자체를 저장하는 blob을 사용할 수 있음.


db자체에 이미지를 저장하게 되면 이미지가 훼손될 가능성이 있거나 이미지를 글자로 변환할 때 변환에 문제가 생길 가능성이 높음


db 자체에 이미지를 저장하게 되면 비용이 많이 들기 때문에 많이 사용하지는 않음

이미지를 저장할 때 sql 자료형(varchar2)로 이미지 경로를 설정해주고 설정한 이미지 경로를 가져오는 방식을 진행

이미지가 저장되는 경로
src/main/resources
/static = css/js/font 처럼 공개 가능하고 유출이 돼도 문제 없는 코드 작성
/image = 홈페이지에서 공개가 가능하고 공통으로 사용할 수 있는 이미지

회사에서 지정한 이미지 저장경로 
= 회사가 아닌 고객이 올리거나 회사에서 비공개로 이미지를 가져오고 저장하는 경로

라이브러리나 프레임워크가 설정되지 않은 js 코드는 유출이 될 가능성이 높음
라이브러리나 프레임워크로 설정된 js 코드는 코드 형식이 라이브러리, 프레임워크의 형식으로 되어 있어 외부에서 코드를 유추하기 어려움

만약에 사진을 저장할 폴더가 존재하지 않거나 폴더 안의 이미지 이름과 형식이 모두 일치해서 덮어씌우거나 할 때 이미지가 저장이 안될 가능서이 있기 때문에 이미지를 저장할 때는

1. 이미지를 불러오거나 저장할 경로가 존재하는지 확인
    -> 경로가 존재하지 않아 불러오지 못할 때
    : 이미지를 불러오는 데 실패했습니다. 라는 이미지 보여주기

    -> 이미지를 저장할 때 폴더가 존재하지 않을 경우
    : 이미지 경로 확인. 원하는 경로가 없으면 없으면 생성

2. 이름이 중복될 경우
    -> 이미지를 저장할 때 이름이 중복될 경우
    : 기존에 있던 이미지와 이름, 파일 형식이 중복되면 저장 당시의 시간을 이름에 붙여서 저장함
    ex)image-2024-06-24.jpg

 

 

imgUpload.html - 이미지를 업로드할 수 있는 페이지 작성

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="utf-8">
<title>돼지 사진 업로드</title>
<link rel="stylesheet" href="/css/style.css">
</head>
<body>
	<div class="container">
		<h1>돼지 사진 업로드</h1>
		<form action="/upload" method="post" enctype="multipart/form-data">
			<div>
				<label>돼지 이름 : </label>
				<input type="text" th:field="${p.pig_name}" required>
				<!-- 방법 2번 : <input type="text" name="pig_name" required> -->
			</div>
			<div>
				<label>돼지 나이 : </label>
				<input type="number" th:field="${p.pig_age}" required>
			</div>
			<div>
				<label>돼지 이미지 : </label>
				<input type="file" th:field="${p.pig_image_path}" required>
			</div>
			<button>업로드</button>
		</form>
	</div>
</body>
</html>

 

-----------------------------------------------------------------------------------------------------------------------

 

Pig-Mapper.xml에 다음과 같은 구문 추가

 

	<insert id="uploadPig" parameterType="com.khmall.dto.Pig">
		INSERT INTO pigs (pig_id, pig_name, pig_age, pig_image_path) 
		VALUES (pig_seq.NEXTVAL, #{pig_name}, #{pig_age}, #{pig_image_path})
	</insert>

 

-----------------------------------------------------------------------------------------------------------------------

 

PigMapper, PigService, PigController에 다음과 같은 구문 추가

 

PigMapper

	//돼지 정보 db에 업로드하기
	public void uploadPig(Pig pig);

 

PigService

//uploadPig
	public void uploadPig(String pig_name, int pig_age, MultipartFile file) {
		//파일 이름을 가져오기
		String fileName = file.getOriginalFilename();
		System.out.println("file Name : " + fileName);
		
		//String uploadDir = "C:/Users/user1/servlet_jsp_workspace/demoProject3-mybatis-mapper-select-image/src/main/resources/static/images";
		//맨 끝에 /로 닫아주지 않으면 static/images/ 안에 이미지가 생성되는 것이 아니라
		//static 바로 밑에 생성되기 때문에 이미지가 보이지 않음.
		
		String uploadDir = "C:/Users/user1/servlet_jsp_workspace/demoProject3-mybatis-mapper-select-image/src/main/resources/static/images/";
		
		File imgFile = new File(uploadDir + fileName);
		
		//이미지 파일을 저장하는 폴더가 존재하지 않을 경우 생성하는 코드
		//저장하고자 하는 파일 경로 설정
		
		if(!imgFile.exists()) { //이미지 폴더가 존재하지 않을 때 폴더 생성
			imgFile.mkdirs(); //폴더가 존재하지 않을 경우 지정했던 위치에 생성
		}
		
		try {
			
			file.transferTo(imgFile);//이미지를 폴더에 저장하는 코드
			
			//업로드 한 다음에 저장된 이미지 경로와 함께 돼지 정보를 저장하는 서비스 작성
			Pig pig = new Pig();
			pig.setPig_name(pig_name);
			pig.setPig_age(pig_age);
			//pig.setPig_image_path(uploadDir); //파일 이름만 저장
			
			//파일 경로와 이름을 같이 저장하기
			pig.setPig_image_path("/images/"+fileName); //-> db에 /images/파일명.jpg로 저장됨
			/* uploadDir -> fileName으로 변경 */
			pigMapper.uploadPig(pig);
			System.out.println("파일 업로드 Service를 성공적으로 완료 했습니다.");
					
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

 

 

PigController

	// 돼지 정보를 올릴 수 있는 주소로 이동할 수 있는 GetMapping
	@GetMapping("/imgUpload") //html 파일과 java 파일이 만나는 지점
	public String uploadForm(Model model) {
		model.addAttribute("p", new Pig()); //db에 올릴 수 있는 공간 생성
		return "imgUpload"; // html 파일 이름
	}
	
	
	//돼지 정보 db에 업로드 PostMapping
	@PostMapping("/upload")
	public String uploadPig(
			//@RequstParam을 읽어서 파일을 하나씩 가져오기 설정
			@RequestParam("pig_name") String pig_name,
			@RequestParam("pig_age") int pig_age,
			@RequestParam("pig_image_path") MultipartFile file,
			
			Model model) { 
		
		pigService.uploadPig(pig_name, pig_age, file);
		
		log.info("pigUpload 확인");
		
		return "redirect:/"; // upload 완료되면 메인 페이지로 이동해서 등록됐는지 확인

 

 

----------------------------------------------------------------------------------------------------------------------------------

 

업로드 하는 창
업로드 한 이후의 index