(1)에서는 기본적인 프로젝트의 기초틀을 만들었다.
이번에는 insert를 만들어 보려고한다!
자 만들어 보자
1. Jsp 검증 로직 구현
<c:when test="${login != null}">
<p>
<img src="../resources/img/profile.png"> ${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. 동작 확인
학원에서 배운내용을 정리를 하는거지만 정말 어렵다.
나중에 다시 코드리뷰를 해보아야겠다.
주인장 Git : https://github.com/MoonSeokHyun
'Spring > 학원에서 배운거정리 끄적' 카테고리의 다른 글
(Spring /Java) SNS 스타일 게시판 만들기(4)😁 (0) | 2022.02.27 |
---|---|
(Spring /Java) SNS 스타일 게시판 만들기(3)😁 (0) | 2022.02.24 |
(Spring /Java) SNS 스타일 게시판 만들기(1)😁 (0) | 2022.02.21 |
(Spring /Java) 스프링 파일 업로드 구현 (2) | 2022.02.20 |
(Spring /Java)이메일 인증 구현하기😎 (4) | 2022.02.17 |