게시글 목록 페이지에서 글쓰기 버튼을 누르면 글쓰기 페이지로 이동한다. 내용을 입력하면 데이터베이스에 저장 처리까지!(파일 업로드 기능)
css와 데이터베이스 자료는 생성되어 있던 것 사용
writeForm.jsp
)BoardController
)BoardService
, BoardDao
)BoardService
, BoardDao
)BoardService
, MemberDao
)File upload
HTML의<input>
태그의 file type은 기본적인 파일 선택 창을 제공.
Multi-part
한 웹 문서 안에 문자와 바이너리 데이터(이미지, 동영상, 음성 및 기타 형식의 파일 등)가 함께
포함되어 있는 상황.
MIME(Multipurpose Internet Mail Extenstion)
전자우편(e-mail)을 위한 인터넷 표준 포맷.
content-type : 문서에 포함된 내용을 구성한 형태 지정.
기본 형태 - text/plain이나 text/html.
다중의 내용이 포함되면 multipart/...
<section>
<div class="content">
<form action="writeProc" class="write-form" method="post" enctype="multipart/form-data">
<div class="user-info">
<div class="user-info-sub">
<p>등급 [${mb.g_name}]</p>
<p>POINT [${mb.m_point}]</p>
</div>
</div>
<h2 class="login-header">글쓰기</h2>
<!-- 로그인한 id(숨김), 제목, 내용 -->
<input type="hidden" name="b_id" value="${mb.m_id}">
<input type="text" class="write-input" name="b_title"
autofocus placeholder="제목" required>
<textarea name="b_contents" class="write-input ta" rows="15" placeholder="내용을 적어주세요."></textarea>
<div class="filebox">
<label for="file">업로드</label>
<input type="file" name="files" id="file" multiple>
<input type="text" class="upload-name" value="파일선택" readonly>
</div>
<div class="btn-area">
<input type="submit" class="btn-write" value="W">
<input type="reset" class="btn-write" value="R">
<input type="button" class="btn-write" value="B" onclick="backbtn()">
</div>
</form>
</div>
</section>
B
버튼 클릭시 뒤로 이동할 스크립트와 파일 업로드시 파일 제목처리용 함수가 필요하다.
//B 버튼 클릭시 뒤로 가는 스크립트
function backbtn(){
let urlstr = "/list?";
let col = "${sdto.colname}";
let keyw = "${sdto.keyword}";
if(col == null || col == ''){//검색을 수행하지 않은 경우
urlstr += "pageNum=${pageNum}";
} else{//검색을 한 경우
urlstr += "colname=${sdto.colname}&keyword=${sdto.keyword}&pageNum=${sdto.pageNum}";
}
console.log(urlstr);
location.href = urlstr;
}
//파일 제목 처리용 함수
$("#file").on("change",function(){
//파일 선택 창에서 업로드할 파일을 선택한 후 '열기' 버튼을 누르면 change 이벤트가 발생.
console.log($("#file"));
let files = $("#file")[0].files;
console.log(files);
let fileName = "";
if(files.length > 1){
fileName = files[0].name + " 외 " + (files.length -1) + "개";
} else if(files.length == 1){
fileName = files[0].name;
} else {
fileName = "파일선택";
}
$(".upload-name").val(fileName);
});
파일이 한 개만 업로드 될 때는 파일명 그대로 노출
파일이 한 개 이상일 때는 맨 처음에 업로드 한 파일의 이름만 노출되고 나머지는 외 n개
로 표현한다.
//글쓰기 페이지 이동 메소드
@GetMapping("writeForm")
public String writeForm(){
log.info("writeForm()");
return "writeForm";
}
//글쓰기 작업 처리 메소드
//멀티파트 데이터를 처리하는 메소드의 첫번째 매개변수는
//Multipart 파일 목록(List)여야 한다.
//List 앞에 @RequestPart 어노테이션을 붙인다.
@PostMapping("writeProc")
public String writeProc(@RequestPart List<MultipartFile> files,
BoardDto board, HttpSession session,
RedirectAttributes rttr){
log.info("writeProc()");
String view = bServ.boardWrite(files, board, session, rttr);
return view;
}
public String boardWrite(List<MultipartFile> files, BoardDto board, HttpSession session, RedirectAttributes rttr){
log.info("boardWrite()");
String view = null;
String msg = null;
try {
//글 내용 저장.
bDao.insertBoard(board);
log.info("게시글 번호 : " + board.getB_num());
//파일 업로드 처리
fileUpload(files, session, board);
//작성한 회원의 point 증가 처리(session)
MemberDto member = (MemberDto) session.getAttribute("mb");
int point = member.getM_point() + 10;
if(point > 100){//100 초과하지 않도록
point = 100;
}
member.setM_point(point);
//DB member 테이블 수정(update)
mDao.updateMemberPoint(member);
session.setAttribute("mb", member);
//같은 이름으로 세션에 저장하면 덮어쓰기가 된다.
//글 작성 후 목록 첫 페이지로 이동.
view = "redirect:list?pageNum=1";
msg = "글 작성 성공";
} catch (Exception e){
e.printStackTrace();
view = "redirect:writeForm";
msg = "글 작성 실패";
}
rttr.addFlashAttribute("msg", msg);
return view;
}
@Mapper
public interface BoardDao {
//게시글 저장 메소드 선언
void insertBoard(BoardDto board);
}
DB에 사용자가 입력한 내용을 저장하는 쿼리문
<insert id="insertBoard" parameterType="BoardDto"
useGeneratedKeys="true" keyProperty="b_num">
<selectKey keyProperty="b_num" resultType="Integer" order="AFTER">
select last_insert_id()
</selectKey>
insert into board values (null, #{b_title}, #{b_contents}, #{b_id}, default, default)
</insert>
BoardService
소스에서 파일 업로드 메소드를 사용하는 부분은 글쓰기 작업 처리 영역에 포함되어 있어서 생략한다.
//파일 업로드 처리 <- 이 부분
fileUpload(files, session, board);
private void fileUpload(List<MultipartFile> files, HttpSession session, BoardDto board) throws Exception{
log.info("fileUpload()");
//파일 저장 위치
String realPath = session.getServletContext().getRealPath("/");
realPath += "upload/"; //업로드용 폴더 : upload
File folder = new File(realPath);
if(folder.isDirectory() == false){
folder.mkdir();//폴더 생성.
}
//파일 저장 처리(목록이므로 반복 처리)
for(MultipartFile mf : files){
//파일명(원래 이름) 추출
String orname = mf.getOriginalFilename();
if(orname.equals("")){
return;
}
//파일 정보 저장
BfileDto bf = new BfileDto();
bf.setBf_bnum(board.getB_num());//게시글 번호
bf.setBf_oriname(orname);//원래 파일 이름
String sysname = System.currentTimeMillis()
+ orname.substring(orname.lastIndexOf("."));
bf.setBf_sysname(sysname);
//파일 저장(to upload folder)
File file = new File(realPath + sysname);
mf.transferTo(file);
//파일 정보 저장(DB)
bDao.insertFile(bf);
}//for end
}//method end
@Mapper
public interface BoardDao {
//게시글 파일 저장 메소드
void insertFile(BfileDto df);
}
<insert id="insertFile" parameterType="BfileDto">
insert into boardfile
values (null, #{bf_bnum}, #{bf_oriname}, #{bf_sysname})
</insert>
웹 페이지
아직 상세보기 페이지를 만들지는 않았지만 파일 업로드를 하면 페이지에 업로드된 이미지 파일명이 보인다. 중복 파일명 업로드를 피하기 위해 DB에는 파일명을 바꿔서 업로드 한다.
데이터베이스
bf_oriname
: 원래의 파일 이름
bf_sysname
: DB에 저장된 파일 이름
BoardService
소스에서 회원 포인트 증가 메소드를 사용하는 부분은 글쓰기 작업 처리 영역에 포함되어 있어서 생략한다.
//작성한 회원의 point 증가 처리(session) <- 이 부분
MemberDto member = (MemberDto) session.getAttribute("mb");
int point = member.getM_point() + 10;
if(point > 100){//100 초과하지 않도록
point = 100;
}
member.setM_point(point);
//DB member 테이블 수정(update)
mDao.updateMemberPoint(member);
session.setAttribute("mb", member);
//같은 이름으로 세션에 저장하면 덮어쓰기가 된다.
MemberDto
의 member를 불러와서 글을 쓴 회원의 포인트를 증가시킨다. 최대 포인트는 100점. (100점 이상 넘어가지 않도록 조절)
@Mapper
public interface MemberDao {
//회원 포인트 수정 메소드
void updateMemberPoint(MemberDto member);
}
<update id="updateMemberPoint">
update member
set m_point=#{m_point}
where m_id=#{m_id}
</update>
계속 글쓰기 테스트를 해보다 어느새 다이아
등급이 되어버린 나...
2023.05.25 작성