반응형


(1)에서는 기본적인 프로젝트의 기초틀을 만들었다. 

이번에는 insert를 만들어 보려고한다! 

 

자 만들어 보자 

 


1. Jsp 검증 로직 구현

  <c:when test="${login != null}">
<p>
<img src="../resources/img/profile.png">&nbsp;&nbsp;${login.userName}님
 </p>
    <ul>
        <li>내정보</li>
        <li>내쿠폰</li>
        <li>내 좋아요 게시물</li>
	 </ul>
</c:when>
<c:otherwise>

 

   $(function() {
      
      //등록하기 버튼 클릭 이벤트
      $('#uploadBtn').click(function() {
         regist();
      });
      
      //등록을 담당하는 함수
      function regist() {
         //세션에서 현재 로그인 중인 사용자 정보(아이디)를 얻어오자
         const user_id = '${sessionScope.login.userId}';
         //자바스크립트의 파일 확장자 체크 검색.
         let file = $('#file').val();
         
         console.log(user_id);
         console.log(file);
         //.을 제거한 확장자만 얻어낸 후 그것을 소문자로 일괄 변경
         file = file.slice(file.indexOf('.') + 1).toLowerCase();
         console.log(file);
         if(file !== 'jpg' && file !== 'png' && file !== 'jpeg' && file !== 'bmp') {
            alert('이미지 파일(jpg, png, jpeg, bmp)만 등록이 가능합니다.');
            $('#file').val('');
            return;
         } else if(user_id === '') { //세션 데이터가 없다 -> 로그인 x
            alert('로그인이 필요한 서비스입니다.');
            return;
         }

세션데이터가 없을경우 글 등록을 하지 못하게 하였다.

그리고 얻어온 세션 아이디로 글을 올린 사람에 대한 정보를 쿼리문으로 넘겨 줄 것이다.

 

우선 file이라는 변수로 file의 값을 가져온다. 

그 후 파일 업로드가 끝나면 slice 함수로 .png 등 확장자를 잘라내어 

tolowerCase로 소문자로 변경해준다.

 

그 뒤 이미지 파일만 올릴 수 있게

if문 으로 검증 로직을 구현 해준다. 

 

즉 로그인 안됨 = 파일을 올릴 수없음

로그인 함 = 이미지 파일만 올릴 수있음

이 두가지 관문을 거쳐야 파일을 올릴 수있게 처리를 하였다.

 

 

미리보기 기능

 

      function readURL(input) {
           if (input.files && input.files[0]) {
              
               var reader = new FileReader(); //비동기처리를 위한 파읽을 읽는 자바스크립트 객체
               //readAsDataURL 메서드는 컨텐츠를 특정 Blob 이나 File에서 읽어 오는 역할 (MDN참조)
              reader.readAsDataURL(input.files[0]); 
               //파일업로드시 화면에 숨겨져있는 클래스fileDiv를 보이게한다
               $(".fileDiv").css("display", "block");
               
               reader.onload = function(event) { //읽기 동작이 성공적으로 완료 되었을 때 실행되는 익명함수
                   $('#fileImg').attr("src", event.target.result); 
                   console.log(event.target)//event.target은 이벤트로 선택된 요소를 의미
              }
           }
       }
      $("#file").change(function() {
           readURL(this); //this는 #file자신 태그를 의미
           
       });

1) 이미지가 1개인 경우

미리보기 이미지가 표시될 이미지 태그를 생성하고, input file 태그를 생성하고, 자바스크립트의 FileReader()를 통해 이미지가 로딩되면 이미지 태그의 src 속성이 교체되도록 합니다.

 

 

 

 

2. 컨트롤러 제작

 

	@GetMapping("/snsList")
	public void snsList() {}
	
	@PostMapping("/upload")
	@ResponseBody
	public String upload(MultipartFile file, String content, 
						 HttpSession session) {
		
		try {
			
			String writer = ((UserVO)session.getAttribute("login")).getUserId();
			
			//날짜별로 폴더를 생성해서 파일을 관리
			SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
			Date date = new Date();
			String fileLoca = sdf.format(date);
			
			//저장할 폴더 경로
			String uploadPath = "C:\\Users\\mls00\\OneDrive\\바탕 화면\\upload\\" + fileLoca;
			
			File folder = new File(uploadPath);
			if(!folder.exists()) {
				folder.mkdir(); //폴더가 존재하지 않는다면 생성해라.
			}
			
			String fileRealName = file.getOriginalFilename();
			
			//파일명을 고유한 랜덤 문자로 생성.
			UUID uuid = UUID.randomUUID();
			String uuids = uuid.toString().replaceAll("-", "");
			
			//확장자를 추출합니다.
			String fileExtension = fileRealName.substring(fileRealName.indexOf("."), fileRealName.length());
			
			System.out.println("저장할 폴더 경로: " + uploadPath);
			System.out.println("실제 파일명: " + fileRealName);
			System.out.println("폴더명: " + fileLoca);
			System.out.println("확장자: " + fileExtension);
			System.out.println("고유랜덤문자: " + uuids);
			
			String fileName = uuids + fileExtension;
			System.out.println("변경해서 저장할 파일명: " + fileName);
			
			//업로드한 파일을 서버 컴퓨터의 지정한 경로 내에 실제로 저장.
			File saveFile = new File(uploadPath + "\\" + fileName);
			file.transferTo(saveFile);
			
			//DB에 insert 작업을 진행.
			SnsBoardVO snsVO = new SnsBoardVO(0, writer, uploadPath, fileLoca, fileName, fileRealName, content, null);
			service.insert(snsVO);
			
			
			return "success";
			
		} catch (Exception e) {
			System.out.println("업로드 중 에러 발생: " + e.getMessage());
			return "fail"; //에러가 났을 시에는 실패 키워드를 반환.
		}
		
	}

 

@GetMapping("/snsList") void 처리로 페이지 이동을 할 수 있게 처리 

 

로그인 세션을 가져와  로그인한 아이디의 값을 가져온다. 

 

날자별로 폴더를 생성해서 관리를 하려고한다.

자바 객체인 SimpleDateFormat을 활용하여

날자를 생성해주고

Date date = new Date(); 하면 오늘 날자가 생성된다.

fileloca라는 변수에 저장해 둔다 (20220215) 이런식으로 나옴

 

저장할 폴더의 경로를 선택해준다.

 

String uploadPath = 실제사용할경로 + fileloca

 

그 후 자바 FIle객체를 사용하여 

 

          exist() - File 객체가 참조하는 파일 또는 디렉토리가 실제로 존재하면 true를, 그렇지

                            않으면 false를 리턴한다.

 

메소드를 활용하여 파일이 한번 생성 된 뒤 중복 생성을 방지한다.


String fileRealName = file.getOriginalFilename();로 파일 고유의 이름을 추출

 

UUID uuid = UUID.randomUUID();
String uuids = uuid.toString().replaceAll("-", "");

로 랜덤한 이름을 추출 생성 해준뒤 

 

자바스크립트와 같이 확장자를 추출한다.(substring 활용)

String fileExtension = fileRealName.substring(fileRealName.indexOf("."), fileRealName.length());

 

그 후 이름을 변경한 파일의 이름을 변수 명으로 담는다.

String fileName = uuids + fileExtension;

 

업로드한 파일을 서버 컴퓨터의 지정한 경로 내에 실제로 저장.
File saveFile = new File(uploadPath + "\\" + fileName);
file.transferTo(saveFile);

MultipartFile 의 transferTo() 라는 메소드를 사용해서 원하는 위치에 저장해줍니다

//DB에 insert 작업을 진행.
SnsBoardVO snsVO = new SnsBoardVO(0, writer, uploadPath, fileLoca, fileName, fileRealName, content, null);
service.insert(snsVO);

 

 

 

2-1 서비스제작

 

	@Override
	public void insert(SnsBoardVO vo) {
		mapper.insert(vo);
	}

VO값을 컨트롤러로 보내준다.

 

2-2 Mapper 제작

 

 

	<!-- 등록하기 -->
	<insert id="insert">
		INSERT INTO snsboard
		(bno, writer, uploadpath, fileloca, filename, filerealname, content)
		VALUES
		(snsboard_seq.NEXTVAL, #{writer}, #{uploadpath}, #{fileloca}, #{filename}, #{filerealname}, #{content})
	</insert>

원래 나중에 resultmap을 써야하지만 나는 변수명과 컬럼값을 다 맞춰 벼렸다.. 

다음부터는 원칙을 지키자

sql은 snake_case!!

jaca CamelCase!!

 

3. 비동기 통신(ajax)

 

const formData = new FormData();
         const data = $('#file');
         
         console.log('폼 데이터: ' + formData);
         console.log('data: ' + data);
         console.log(data[0]);
         console.log(data[0].files); //파일 태그에 담긴 파일 정보를 확인하는 키값.
         console.log(data[0].files[0]);
         
         //data[index] -> 파일 업로드 버튼이 여러 개 존재할 경우 요소의 인덱스를 지목해서 가져오는 법.
         //우리는 요소를 id로 취득했기 때문에 하나만 찍히지만, class이름 같은거로 지목하면 여러개가 취득되겠죠?
         //files[index] -> 파일이 여러개 전송되는 경우, 몇 번째 파일인지를 지목.
         //우리는 multiple 속성을 주지 않았기 때문에 0번 인덱스 밖에 없는 겁니다.
         
         //FormData 객체에 사용자가 업로드한 파일의 정보들이 들어있는 객체를 전달.
         formData.append('file', data[0].files[0]);
         //content(글 내용) 값을 얻어와서 폼 데이터에 추가
         const content = $('#content').val();
         formData.append('content', content);
         
         //비동기 방식으로 파일 업로드 및 게시글 등록을 진행.
         $.ajax({
            url: '<c:url value="/snsBoard/upload" />',
            type: 'post',
            data: formData, //폼데이터 객체를 넘깁니다.
            contentType: false, //ajax 방식에서 파일을 넘길때는 반드시 false로 처리 -> "multipart/form-data"로 선언됨.
            processData: false, //폼 데이터를 &변수=값&변수=값... 형식으로 변경되는 것을 막는 요소.
            success: function(result) {
               if(result === 'success') {
                  $('#file').val(''); //파일선택지 비우기
                  $('#content').val(''); //글 영역 비우기
                  $('.fileDiv').css('display', 'none'); //미리보기 감추기
                  getList(1, true); //글 목록을 호출
               } else {
                  alert('업로드에 실패했습니다. 관리자에게 문의해 주세요.');
               }
            },
            error: function(request, status, error) {
               console.log('code: ' + request + '\n' + 'message: ' + request.responseText + '\n' + 'error: ' + error);
               alert('업로드에 실패했습니다. 관리자에게 문의해 주세요.');
            }
            
         }); //end ajax
               
      } //end regist()

폼데이터를 활용하여 컨트롤러에게 비동기 통신으로 전달한다.

 

FromData란 ajax로 폼 전송을 가능하게 해주는 FormData 객체입니다.

보통은 Ajax로 폼(form 태그) 전송을 할 일이 거의 없습니다.

주로 JSON 구조로 "KEY-VALUE" (키와 값) 구조로 데이터를 전송합니다.

 

하지만,

form전송이 필요한 경우가 있는데, 이미지를 ajax로 업로드할 때 필요합니다.

이미지는 base64, buffer, 2진 data 형식으로 서버로 전송해도 됩니다.

 

하지만 추천 드리는 방법은 input[type=file]을 사용해 form(폼)을 통해서 업로드를 하는 것 입니다.

보통, form을 제출하면 action 속성에 의해 지정한 페이지로 이동하면서 데이터를 전송합니다.

ajax 반대로 제출 버튼을 누르면 기본 폼 동작은 e.preventDefault()  로 멈추고, 페이지 전환 없이 데이터를 전송합니다.

 

페이지 전환 없이 폼 데이터를 제출 하고 싶을 때 바로 FormData 객체를 사용합니다.

기존에 스캔 설정이랑은 해서 바로 테스트를 해보면 될 듯하다. 

 

 


4. 동작 확인

로그인 세션값 불러오기 및 화면
이미지 미리보기 구현
컨트롤러 정상 동작 확인

 

sql 업로드 확인

학원에서 배운내용을 정리를 하는거지만 정말 어렵다.

나중에 다시 코드리뷰를 해보아야겠다. 

 

 

주인장 Git : https://github.com/MoonSeokHyun

반응형

+ Recent posts