DB에 테이블 생성
create table tbl_attach(
uuid varchar2(100) not null,
uploadPath varchar2(200) not null,
fileName varchar2(100) not null,
filetype char(1) default 'I',
bno number
);
alter table tbl_attach
add constraint tbl_attach_uuid_PK primary key(uuid);
alter table tbl_attach
add constraint tbl_attach_bno_FK foreign key(bno) references tbl_board(bno);
src/main/java 경로에 있는 domain 폴더에 BoardAttachDTO 파일 생성 후 작성
@Data
public class BoardAttachDTO {
private String uuid;
private String uploadPath;
private String fileName;
private boolean filetype;
private int bno;
}
BoardDTO 파일 하단에 코드 추가
private List<BoardAttachDTO> attachList;
src/main/java 경로에 있는 mapper 패키지에 BoardAttachMapper 인터페이스 생성 후 작성
public interface BoardAttachMapper {
public void insert(BoardAttachDTO boardAttachDto);
public void delete(String uuid);
public List<BoardAttachDTO> findByBno(int bno);
}
src/main/resources경로에 있는 mappers 패키지에 BoardAttachMapper.xml 파일 생성 후 작성
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.hanul.springstudent.mapper.BoardAttachMapper">
<insert id="insert">
INSERT INTO tbl_attach(uuid, uploadPath, fileName, filetype, bno)
VALUES (#{uuid}, #{uploadPath}, #{fileName}, #{filetype}, #{bno})
</insert>
<delete id="delete">
DELETE
FROM tbl_attach
WHERE uuid = #{uuid}
</delete>
<select id="findByBno" resultType="com.hanul.springstudent.domain.BoardAttachDTO">
SELECT *
FROM tbl_attach
WHERE bno = #{bno}
</select>
</mapper>
register.jsp 파일 수정
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%>
<%@include file="../includes/header.jsp"%>
<c:set var="contextPath" value="${pageContext.request.contextPath == '/' ? '' : pageContext.request.contextPath }" scope="application" />
<style>
.uploadResult {
width: 100%;
background-color: gray;
}
.uploadResult ul {
display: flex;
flex-flow: row;
justify-content: center;
align-items: center;
}
.uploadResult ul li {
list-style: none;
padding: 10px;
}
.uploadResult ul li img {
width: 100px;
}
.bigPictureWrapper {
position: absolute;
display: none;
justify-content: center;
align-items: center;
top:0%;
width:100%;
height:100%;
background-color: gray;
z-index: 100;
}
.bigPicture {
position: relative;
display:flex;
justify-content: center;
align-items: center;
}
.bigPicutre img {
width: 600px;
}
</style>
<script type="text/javascript">
$(document).ready(function() {
var formObj = $("form[role='form']");
$("button[type='submit']").on("click", function(e){
e.preventDefault();
console.log("submit clicked");
var str = "";
$(".uploadResult ul li").each(function(i, obj){
var jobj = $(obj);
console.dir(jobj);
console.log("-------------------------");
console.log(jobj.data("filename"));
str += "<input type='hidden' name='attachList["+i+"].fileName' value='"+jobj.data("filename")+"'>";
str += "<input type='hidden' name='attachList["+i+"].uuid' value='"+jobj.data("uuid")+"'>";
str += "<input type='hidden' name='attachList["+i+"].uploadPath' value='"+jobj.data("path")+"'>";
str += "<input type='hidden' name='attachList["+i+"].filetype' value='"+ jobj.data("type")+"'>";
});
console.log(str);
formObj.append(str).submit();
});
var regex = new RegExp("(.*?)\.(exe|sh|zip|alz)$");
var maxSize = 5242880; //5MB
function checkExtension(fileName, fileSize) {
if(fileSize >= maxSize) {
alert("파일 사이즈 초과");
return false;
}
if(regex.test(fileName)) {
alert("해당 종류의 파일은 업로드할 수 없습니다.");
return false;
}
return true;
}
$("input[type='file']").change(function(e){
var formData = new FormData();
var inputFile = $("input[name='uploadFile']");
var files = inputFile[0].files;
for(var i = 0; i < files.length; i++){
if(!checkExtension(files[i].name, files[i].size) ){
return false;
}
formData.append("uploadFile", files[i]);
}
$.ajax({
url: "${contextPath}/uploadAjaxAction",
processData: false,
contentType: false,data:
formData,type: "POST",
dataType:"json",
success: function(result){
console.log(result);
showUploadResult(result);
}
}); //$.ajax
});
function showUploadResult(uploadResultArr) {
if(!uploadResultArr || uploadResultArr.length == 0) {
return;
}
var uploadUL = $(".uploadResult ul");
var str ="";
$(uploadResultArr).each(function(i, obj) {
if(obj.image){
var fileCallPath = encodeURIComponent(obj.uploadPath+ "/s_" + obj.uuid + "_" + obj.fileName);
str += "<li data-path='" + obj.uploadPath + "'";
str +=" data-uuid='" + obj.uuid + "' data-filename='" + obj.fileName + "' data-type='" + obj.image + "'"
str +" ><div>";
str += "<span> " + obj.fileName + "</span>";
str += "<button type='button' data-file=\'" + fileCallPath + "\' "
str += "data-type='image' class='btn btn-warning btn-circle'><i class='fa fa-times'></i></button><br>";
str += "<img src='${contextPath}/display?fileName=" + fileCallPath + "'>";
str += "</div>";
str +"</li>";
} else {
var fileCallPath = encodeURIComponent(obj.uploadPath + "/" + obj.uuid + "_" + obj.fileName);
var fileLink = fileCallPath.replace(new RegExp(/\\/g),"/");
str += "<li "
str += "data-path='" + obj.uploadPath + "' data-uuid='" + obj.uuid + "' data-filename='" + obj.fileName + "' data-type='" + obj.image + "' ><div>";
str += "<span> " + obj.fileName + "</span>";
str += "<button type='button' data-file=\'" + fileCallPath + "\' data-type='file' "
str += "class='btn btn-warning btn-circle'><i class='fa fa-times'></i></button><br>";
str += "<img src='${contextPath}/resources/img/attach.png'></a>";
str += "</div>";
str +"</li>";
}
});
uploadUL.append(str);
}
$(".uploadResult").on("click", "button", function(e) {
console.log("delete file");
var targetFile = $(this).data("file");
var type = $(this).data("type");
var targetLi = $(this).closest("li");
$.ajax({
url: "${contextPath}/deleteFile",
data: {fileName: targetFile, type:type},
dataType:"text",
type: "POST",
success: function(result){
alert(result);
targetLi.remove();
}
}); //$.ajax
});
});
</script>
<div class="row">
<c:set var="contextPath" value="${pageContext.request.contextPath == '/' ? '' : pageContext.request.contextPath }" scope="application" />
<div class="col-lg-12">
<h1 class="page-header">Board Register</h1>
</div>
<!-- /.col-lg-12 -->
</div>
<!-- /.row -->
<div class="row">
<div class="col-lg-12">
<div class="panel panel-default">
<div class="panel-heading">Board Register</div>
<!-- /.panel-heading -->
<div class="panel-body">
<form role="form" action="${contextPath}/board/register" method="post">
<div class="form-group">
<label>Title</label> <input class="form-control" name="title">
</div>
<div class="form-group">
<label>Text area</label>
<textarea class="form-control" rows="3" name="content"></textarea>
</div>
<div class="form-group">
<label>Writer</label> <input class="form-control" name="writer">
</div>
<button type="submit" class="btn btn-default">Submit
Button</button>
<button type="reset" class="btn btn-default">Reset Button</button>
</form>
</div>
<!-- end panel-body -->
</div>
<!-- end panel-body -->
</div>
<!-- end panel -->
</div>
<!-- /.row -->
<div class="row">
<div class="col-lg-12">
<div class="panel panel-default">
<div class="panel-heading">File Attach</div>
<!-- /.panel-heading -->
<div class="panel-body">
<div class="form-group uploadDiv">
<input type="file" name="uploadFile" multiple>
</div>
<div class="uploadResult">
<ul>
</ul>
</div>
</div>
<!-- end panel-body -->
</div>
<!-- end panel-body -->
</div>
<!-- end panel -->
</div>
<%@include file="../includes/footer.jsp"%>
BoardController 의 등록메소드 수정
@RequestMapping(value = "/register", method = RequestMethod.POST)
public String registerPOST(BoardDTO bDto, RedirectAttributes rttr) throws Exception {
log.info("register post........................");
if(bDto.getAttachList() != null) {
bDto.getAttachList().forEach(attach -> log.info(attach));
}
service.register(bDto);
rttr.addFlashAttribute("result", bDto.getBno());
return "redirect:/board/list";
}
BoardServiceImpl 수정
@Autowired
private BoardAttachMapper attachMapper;
@Transactional
@Override
public void register(BoardDTO bDto) throws Exception {
bDao.create(bDto);
if (bDto.getAttachList() == null || bDto.getAttachList().size() <= 0) {
return;
}
bDto.getAttachList().forEach(attach -> {
attach.setBno(bDto.getBno());
attachMapper.insert(attach);
});
}
톰캣 구동 후 로컬에서 파일첨부 해보기
등록 후 DB에서 확인하면 잘 등록되어있음
IBoardService 인터페이스에 첨부파일 조회 추상메소드 추가
public List<BoardAttachDTO> getAttachList(int bno);
BoardServiceImpl에서 첨부파일 조회 메소드 구현
@Override
public List<BoardAttachDTO> getAttachList(int bno) {
return attachMapper.findByBno(bno);
}
BoardController에 첨부파일 조회 코드 추가
// 첨부파일 조회
@GetMapping(value = "/getAttachList",
produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
@ResponseBody
public ResponseEntity<List<BoardAttachDTO>> getAttachList(int bno) {
log.info("getAttachList : " + bno);
return new ResponseEntity<>(service.getAttachList(bno), HttpStatus.OK);
}
read.jsp 수정
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%>
<%@include file="../includes/header.jsp"%>
<c:set var="contextPath" value="${pageContext.request.contextPath == '/' ? '' : pageContext.request.contextPath }" scope="application" />
<style>
.uploadResult {
width:100%;
background-color: gray;
}
.uploadResult ul{
display:flex;
flex-flow: row;
justify-content: center;
align-items: center;
}
.uploadResult ul li {
list-style: none;
padding: 10px;
align-content: center;
text-align: center;
}
.uploadResult ul li img{
width: 100px;
}
.uploadResult ul li span {
color:white;
}
.bigPictureWrapper {
position: absolute;
display: none;
justify-content: center;
align-items: center;
top:0%;
width:100%;
height:100%;
background-color: gray;
z-index: 100;
background:rgba(255,255,255,0.5);
}
.bigPicture {
position: relative;
display:flex;
justify-content: center;
align-items: center;
}
.bigPicture img {
width:600px;
}
</style>
<div class="row">
<div class="col-lg-12">
<h1 class="page-header">Board Read</h1>
</div>
<!-- /.col-lg-12 -->
</div>
<!-- /.row -->
<div class="row">
<div class="col-lg-12">
<div class="panel panel-default">
<div class="panel-heading">Board Read Page</div>
<!-- /.panel-heading -->
<div class="panel-body">
<div class="form-group">
<label>Bno</label> <input class="form-control" name="bno" value="${board.bno }" readonly="readonly">
</div>
<div class="form-group">
<label>Title</label> <input class="form-control" name="title" value="${board.title }" readonly="readonly">
</div>
<div class="form-group">
<label>Text area</label>
<textarea class="form-control" rows="3" name="content" readonly="readonly">${board.content }</textarea>
</div>
<div class="form-group">
<label>Writer</label> <input class="form-control" name="writer" value="${board.writer }" readonly="readonly">
</div>
<button data-oper="modify" class="btn btn-default">Modify</button>
<button data-oper="list" class="btn btn-info">List</button>
<form id="operForm" action="${contextPath}/board/modify" method="get">
<input type="hidden" id="bno" name="bno" value="${board.bno}">
<input type="hidden" id="pageNum" name="pageNum" value="${cri.pageNum}">
<input type="hidden" id="amount" name="amount" value="${cri.amount}">
<input type="hidden" name="type" value="${cri.type}">
<input type="hidden" name="keyword" value="${cri.keyword}">
</form>
</div>
<!-- end panel-body -->
</div>
<!-- end panel-body -->
</div>
<!-- end panel -->
</div>
<!-- /.row -->
<div class='bigPictureWrapper'>
<div class='bigPicture'>
</div>
</div>
<div class="row">
<div class="col-lg-12">
<div class="panel panel-default">
<div class="panel-heading">Files</div>
<!-- /.panel-heading -->
<div class="panel-body">
<div class="uploadResult">
<ul>
</ul>
</div>
</div>
<!-- end panel-body -->
</div>
<!-- end panel-body -->
</div>
<!-- end panel -->
</div>
<!-- /.row -->
<div class='row'>
<div class="col-lg-12">
<!-- /.panel -->
<div class="panel panel-default">
<div class="panel-heading">
<i class="fa fa-comments fa-fw"></i> Reply
<button id='addReplyBtn' class='btn btn-primary btn-xs pull-right'>New Reply</button>
</div>
<!-- /.panel-heading -->
<div class="panel-body">
<ul class="chat">
</ul>
<!-- ./ end ul -->
</div>
<!-- /.panel .chat-panel -->
<div class="panel-footer"></div>
</div>
</div>
<!-- ./ end row -->
</div>
<div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h4 class="modal-title" id="myModalLabel">REPLY MODAL</h4>
</div>
<div class="modal-body">
<div class="form-group">
<label>ReplyText</label>
<input class="form-control" name="replytext" value="New Reply!!!!">
</div>
<div class="form-group">
<label>Replyer</label>
<input class="form-control" name="replyer" value="replyer">
</div>
<div class="form-group">
<label>Reply Date</label>
<input class="form-control" name="replyDate" value="2018-01-01 13:13">
</div>
</div>
<div class="modal-footer">
<button id="modalModifyBtn" type="button" class="btn btn-warning">Modify</button>
<button id="modalRemoveBtn" type="button" class="btn btn-danger">Remove</button>
<button id="modalRegisterBtn" type="button" class="btn btn-primary">Register</button>
<button id="modalCloseBtn" type="button" class="btn btn-default">Close</button>
</div>
</div>
<!-- /.modal-content -->
</div>
<!-- /.modal-dialog -->
</div>
<!-- /.modal -->
<script type="text/javascript" src="${contextPath}/resources/js/reply.js"></script>
<script type="text/javascript">
window.onload = function() {
history.pushState(null, null, location.href);
window.onpopstate = function() {
alert("sss");
history.go(1);
};
};
$(document).ready(function() {
var bnoValue = "${board.bno}";
var replyUL = $(".chat");
showList(1);
function showList(page) {
console.log("show list " + page);
replyService.getList(
{bno:bnoValue, contextPath:"${contextPath}", page: page || 1 },
function(replyCnt, list) {
console.log("replyCnt: "+ replyCnt );
console.log("list: " + list);
console.log(list);
if(page == -1){
pageNum = Math.ceil(replyCnt/10.0);
showList(pageNum);
return;
}
var str="";
if(list == null || list.length == 0){
return;
}
for (var i = 0, len = list.length || 0; i < len; i++) {
str +="<li class='left clearfix' data-rno='"+list[i].rno+"'>";
str +=" <div><div class='header'><strong class='primary-font'>["
+ list[i].rno+"] "+list[i].replyer+"</strong>";
str +=" <small class='pull-right text-muted'>"
+ replyService.displayTime(list[i].updatedate)+"</small></div>";
str +=" <p>"+list[i].replytext+"</p></div></li>";
}
replyUL.html(str);
showReplyPage(replyCnt);
});//end function
}//end showList
var pageNum = 1;
var replyPageFooter = $(".panel-footer");
function showReplyPage(replyCnt) {
var endNum = Math.ceil(pageNum / 10.0) * 10;
var startNum = endNum - 9;
var prev = startNum != 1;
var next = false;
if(endNum * 10 >= replyCnt) {
endNum = Math.ceil(replyCnt/10.0);
}
if(endNum * 10 < replyCnt) {
next = true;
}
var str = "<ul class='pagination pull-right'>";
if(prev) {
str+= "<li class='page-item'><a class='page-link' href='"+(startNum -1)+"'>Previous</a></li>";
}
for(var i = startNum ; i <= endNum; i++) {
var active = pageNum == i? "active":"";
str+= "<li class='page-item "+active+" '><a class='page-link' href='"+i+"'>"+i+"</a></li>";
}
if(next) {
str+= "<li class='page-item'><a class='page-link' href='"+(endNum + 1)+"'>Next</a></li>";
}
str += "</ul></div>";
console.log(str);
replyPageFooter.html(str);
}
replyPageFooter.on("click","li a", function(e) {
e.preventDefault();
console.log("page click");
var targetPageNum = $(this).attr("href");
console.log("targetPageNum: " + targetPageNum);
pageNum = targetPageNum;
showList(pageNum);
});
var modal = $(".modal");
var modalInputReplyText = modal.find("input[name='replytext']");
var modalInputReplyer = modal.find("input[name='replyer']");
var modalInputReplyDate = modal.find("input[name='replyDate']");
var modalModifyBtn = $("#modalModifyBtn");
var modalRemoveBtn = $("#modalRemoveBtn");
var modalRegisterBtn = $("#modalRegisterBtn");
$("#modalCloseBtn").on("click", function(e){
modal.modal("hide");
});
$("#addReplyBtn").on("click", function(e){
modal.find("input").val("");
modalInputReplyDate.closest("div").hide();
modal.find("button[id !='modalCloseBtn']").hide();
modalRegisterBtn.show();
$(".modal").modal("show");
});
// 새로운 댓글 처리
modalRegisterBtn.on("click", function(e) {
var reply = {
replytext: modalInputReplyText.val(),
replyer:modalInputReplyer.val(),
contextPath:"${contextPath}",
bno:bnoValue
};
replyService.add(reply, function(result){
alert(result);
modal.find("input").val("");
modal.modal("hide");
showList(-1);
});
});
$(".chat").on("click", "li", function(e){
var reply = {
rno : $(this).data("rno"),
contextPath:"${contextPath}",
};
replyService.get(reply, function(reply){
modalInputReplyText.val(reply.replytext);
modalInputReplyer.val(reply.replyer);
modalInputReplyDate.val(replyService.displayTime(reply.regdate)).attr("readonly","readonly");
modal.data("rno", reply.rno);
modal.find("button[id !='modalCloseBtn']").hide();
modalModifyBtn.show();
modalRemoveBtn.show();
$(".modal").modal("show");
});
});
modalModifyBtn.on("click", function(e){
var reply = {
rno:modal.data("rno"),
replytext: modalInputReplyText.val(),
contextPath:"${contextPath}"
};
replyService.update(reply, function(result) {
alert(result);
modal.modal("hide");
showList(pageNum);
});
});
modalRemoveBtn.on("click", function (e) {
var reply = {
rno : modal.data("rno"),
contextPath:"${contextPath}"
};
replyService.remove(reply, function(result) {
alert(result);
modal.modal("hide");
showList(pageNum);
});
});
});
</script>
<script type="text/javascript">
$(document).ready(function() {
var operForm = $("#operForm");
$("button[data-oper='modify']").on("click", function(e){
operForm.attr("action","${contextPath}/board/modify").submit();
});
$("button[data-oper='list']").on("click", function(e){
operForm.find("#bno").remove();
operForm.attr("action","${contextPath}/board/list")
operForm.submit();
});
});
</script>
<script>
$(document).ready(function() {
(function() {
var bno = "${board.bno}";
$.getJSON("${contextPath}/board/getAttachList", {bno: bno}, function(arr) {
console.log(arr);
var str = "";
$(arr).each(function(i, attach){
if(attach.filetype){
var fileCallPath = encodeURIComponent(attach.uploadPath+ "/s_" + attach.uuid +"_" + attach.fileName);
str += "<li data-path='" + attach.uploadPath + "' data-uuid='" + attach.uuid + "' data-filename='" + attach.fileName + "' data-type='" + attach.filetype + "' ><div>";
str += "<img src='${contextPath}/display?fileName=" + fileCallPath+"'>";
str += "</div>";
str +"</li>";
} else {
str += "<li data-path='" + attach.uploadPath + "' data-uuid='" + attach.uuid + "' data-filename='" + attach.fileName + "' data-type='" + attach.filetype+"' ><div>";
str += "<span> "+ attach.fileName + "</span><br/>";
str += "<img src='${contextPath}/resources/img/attach.png'></a>";
str += "</div>";
str +"</li>";
}
});
$(".uploadResult ul").html(str);
});//end getjson
})();//end function
$(".uploadResult").on("click","li", function(e){
console.log("view image");
var liObj = $(this);
var path = encodeURIComponent(liObj.data("path")+"/" + liObj.data("uuid")+"_" + liObj.data("filename"));
if(liObj.data("type")){
showImage(path.replace(new RegExp(/\\/g),"/"));
} else {
self.location ="${contextPath}/download?fileName=" + path;
}
});
function showImage(fileCallPath){
$(".bigPictureWrapper").css("display","flex").show();
$(".bigPicture")
.html("<img src='${contextPath}/display?fileName="+fileCallPath+"' >")
.animate({width:"100%", height: "100%"}, 1000);
}
$(".bigPictureWrapper").on("click", function(e){
$(".bigPicture").animate({width:"0%", height: "0%"}, 1000);
setTimeout(function(){
$(".bigPictureWrapper").hide();
}, 1000);
});
});
</script>
<%@include file="../includes/footer.jsp"%>
BoardAttachMapper 인터페이스에서 첨부파일 삭제 추상메소드 추가
public void deleteAll(int bno);
BoardAttachMapper.xml에 delete문 추가
<delete id="deleteAll">
DELETE
FROM tbl_attach
WHERE bno = #{bno}
</delete>
BoardServiceImpl의 삭제메소드 수정
@Transactional
@Override
public boolean remove(Integer bno) throws Exception {
attachMapper.deleteAll(bno);
return bDao.delete(bno) == 1;
}
BoardController에서 메소드 추가 및 수정(많아서 전체 복붙함)
@Controller
@RequestMapping("/board")
@Log4j
public class BoardController {
@Autowired
private IBoardService service;
private String uploadPath = "D:\\PDH\\workspace\\sts\\springstudent\\src\\main\\webapp\\resources\\fileUpload";
// 목록 전체 조회
@RequestMapping(value = "/list", method = RequestMethod.GET)
public void listAll(Criteria cri, Model model) throws Exception {
log.info("show all list.....................");
model.addAttribute("list", service.listAll(cri));
int total = service.getTotalCnt(cri);
log.info("total : " + total);
model.addAttribute("pageMaker", new PageDTO(cri, total));
}
// 등록
@RequestMapping(value = "/register", method = RequestMethod.GET)
public void registerGET() throws Exception {
log.info("register get........................");
}
@RequestMapping(value = "/register", method = RequestMethod.POST)
public String registerPOST(BoardDTO bDto, RedirectAttributes rttr) throws Exception {
log.info("register post........................");
if(bDto.getAttachList() != null) {
bDto.getAttachList().forEach(attach -> log.info(attach));
}
service.register(bDto);
rttr.addFlashAttribute("result", bDto.getBno());
return "redirect:/board/list";
}
// 목록 상세보기
//@RequestMapping(value="/read", method = RequestMethod.GET)
//public void read(@RequestParam("bno") int bno, Model model) throws Exception {
// log.info("show read.....................");
// model.addAttribute("board", service.read(bno));
//}
// 수정
//@RequestMapping(value = "/modify", method = RequestMethod.GET)
//public void modifyGET(@RequestParam("bno") int bno, Model model) throws Exception {
// log.info("modify get...............");
// model.addAttribute("board", service.read(bno));
//}
// 상세 + 수정(다중맵핑)
@RequestMapping(value = {"/read", "/modify"}, method = RequestMethod.GET)
public void modifyGET(@RequestParam("bno") int bno, @ModelAttribute("cri") Criteria cri, Model model) throws Exception {
log.info("read or modify..................");
model.addAttribute("board", service.read(bno));
}
@RequestMapping(value = "/modify", method = RequestMethod.POST)
public String modifyPOST(BoardDTO bDto, @ModelAttribute("cri") Criteria cri, RedirectAttributes rttr) throws Exception {
log.info("modify post...............");
if(service.modify(bDto)) {
rttr.addFlashAttribute("result", "success");
}
rttr.addAttribute("pageNum", cri.getPageNum());
rttr.addAttribute("amount", cri.getAmount());
rttr.addAttribute("type", cri.getType());
rttr.addAttribute("keyword", cri.getKeyword());
return "redirect:/board/list";
}
// 삭제
@RequestMapping(value = "/remove", method = RequestMethod.POST)
public String remove(@RequestParam("bno") int bno, @ModelAttribute("cri") Criteria cri, RedirectAttributes rttr) throws Exception {
log.info("remove..................");
List<BoardAttachDTO> attachList = service.getAttachList(bno);
if(service.remove(bno)) {
deleteFiles(attachList);
rttr.addFlashAttribute("result", "success");
}
rttr.addAttribute("pageNum", cri.getPageNum());
rttr.addAttribute("amount", cri.getAmount());
rttr.addAttribute("type", cri.getType());
rttr.addAttribute("keyword", cri.getKeyword());
return "redirect:/board/list";
}
// 첨부파일 조회
@GetMapping(value = "/getAttachList",
produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
@ResponseBody
public ResponseEntity<List<BoardAttachDTO>> getAttachList(int bno) {
log.info("getAttachList : " + bno);
return new ResponseEntity<>(service.getAttachList(bno), HttpStatus.OK);
}
private void deleteFiles(List<BoardAttachDTO> attachList) {
if (attachList == null || attachList.size() == 0) {
return;
}
log.info("delete attach files...............");
log.info(attachList);
attachList.forEach(attach -> {
try {
Path file = Paths.get(uploadPath + "\\" + attach.getUploadPath() + "\\" + attach.getUuid() + "_" + attach.getFileName());
Files.deleteIfExists(file);
if (Files.probeContentType(file).startsWith("image")) {
Path thumbNail = Paths.get(uploadPath + "\\" + attach.getUploadPath() + "\\s_" + attach.getUuid() + "_" + attach.getFileName());
Files.delete(thumbNail);
}
} catch (Exception e) {
log.error("delete file error " + e.getMessage());
}
});
}
BoardServiceImpl 에서 수정 메소드 코드 수정
@Transactional
@Override
public boolean modify(BoardDTO bDto) throws Exception {
attachMapper.deleteAll(bDto.getBno());
boolean modifyResult = bDao.update(bDto) == 1;
if (modifyResult && bDto.getAttachList().size() > 0) {
bDto.getAttachList().forEach(attach -> {
attach.setBno(bDto.getBno());
attachMapper.insert(attach);
});
}
return bDao.update(bDto) == 1;
}
modify.jsp 코드 수정
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%>
<%@include file="../includes/header.jsp"%>
<div class="row">
<c:set var="contextPath" value="${pageContext.request.contextPath == '/' ? '' : pageContext.request.contextPath }" scope="application" />
<div class="col-lg-12">
<h1 class="page-header">Board Modify</h1>
</div>
<!-- /.col-lg-12 -->
</div>
<!-- /.row -->
<div class="row">
<div class="col-lg-12">
<div class="panel panel-default">
<div class="panel-heading">Board Modify Page</div>
<!-- /.panel-heading -->
<div class="panel-body">
<form action="${contextPath}/board/modify" method="post" role="form">
<input type="hidden" name="pageNum" value="${cri.pageNum}">
<input type="hidden" name="amount" value="${cri.amount}">
<input type="hidden" name="type" value="${cri.type}">
<input type="hidden" name="keyword" value="${cri.keyword}">
<div class="form-group">
<label>Bno</label> <input class="form-control" name="bno" value="${board.bno }" readonly="readonly">
</div>
<div class="form-group">
<label>Title</label> <input class="form-control" name="title" value="${board.title }">
</div>
<div class="form-group">
<label>Text area</label>
<textarea class="form-control" rows="3" name="content">${board.content }</textarea>
</div>
<div class="form-group">
<label>Writer</label> <input class="form-control" name="writer" value="${board.writer }" readonly="readonly">
</div>
<!-- html의 data- 속성 이용 -->
<button type="submit" data-oper="modify" class="btn btn-default">Modify</button>
<button type="submit" data-oper="remove" class="btn btn-danger">Remove</button>
<button type="submit" data-oper="list" class="btn btn-info">List</button>
</form>
</div>
<!-- end panel-body -->
</div>
<!-- end panel-body -->
</div>
<!-- end panel -->
</div>
<!-- /.row -->
<div class='bigPictureWrapper'>
<div class='bigPicture'>
</div>
</div>
<style>
.uploadResult {
width:100%;
background-color: gray;
}
.uploadResult ul{
display:flex;
flex-flow: row;
justify-content: center;
align-items: center;
}
.uploadResult ul li {
list-style: none;
padding: 10px;
align-content: center;
text-align: center;
}
.uploadResult ul li img{
width: 100px;
}
.uploadResult ul li span {
color:white;
}
.bigPictureWrapper {
position: absolute;
display: none;
justify-content: center;
align-items: center;
top:0%;
width:100%;
height:100%;
background-color: gray;
z-index: 100;
background:rgba(255,255,255,0.5);
}
.bigPicture {
position: relative;
display:flex;
justify-content: center;
align-items: center;
}
.bigPicture img {
width:600px;
}
</style>
<div class="row">
<div class="col-lg-12">
<div class="panel panel-default">
<div class="panel-heading">Files</div>
<!-- /.panel-heading -->
<div class="panel-body">
<div class="form-group uploadDiv">
<input type="file" name="uploadFile" multiple="multiple">
</div>
<div class="uploadResult">
<ul>
</ul>
</div>
</div>
<!-- end panel-body -->
</div>
<!-- end panel-body -->
</div>
<!-- end panel -->
</div>
<!-- /.row -->
<script type="text/javascript">
$(document).ready(function() {
var formObj = $("form");
$("button").on("click", function(e) {
e.preventDefault();
var operation = $(this).data("oper");
console.log(operation);
if(operation === "remove") {
formObj.attr("action", "${contextPath}/board/remove");
} else if(operation === "list") {
//move to list
formObj.attr("action", "${contextPath}/board/list").attr("method","get");
var pageNumTag = $("input[name='pageNum']").clone();
var amountTag = $("input[name='amount']").clone();
var keywordTag = $("input[name='keyword']").clone();
var typeTag = $("input[name='type']").clone();
formObj.empty();
formObj.append(pageNumTag);
formObj.append(amountTag);
formObj.append(keywordTag);
formObj.append(typeTag);
//self.location = "${contextPath}/board/list";
//return;
} else if (operation === "modify") {
console.log("submit clicked");
var str = "";
$(".uploadResult ul li").each(function(i, obj){
var jobj = $(obj);
console.dir(jobj);
str += "<input type='hidden' name='attachList["+i+"].fileName' value='"+jobj.data("filename")+"'>";
str += "<input type='hidden' name='attachList["+i+"].uuid' value='"+jobj.data("uuid")+"'>";
str += "<input type='hidden' name='attachList["+i+"].uploadPath' value='"+jobj.data("path")+"'>";
str += "<input type='hidden' name='attachList["+i+"].filetype' value='"+ jobj.data("type")+"'>";
});
formObj.append(str).submit();
}
formObj.submit();
});
});
</script>
<script>
$(document).ready(function() {
(function() {
var bno = "${board.bno}";
$.getJSON("${contextPath}/board/getAttachList", {bno: bno}, function(arr) {
console.log(arr);
var str = "";
$(arr).each(function(i, attach){
//image type
if(attach.filetype){
var fileCallPath = encodeURIComponent(attach.uploadPath + "/s_" + attach.uuid + "_" + attach.fileName);
str += "<li data-path='" + attach.uploadPath + "' data-uuid='" + attach.uuid + "' "
str +=" data-filename='" + attach.fileName +"' data-type='" + attach.filetype + "' ><div>";
str += "<span> "+ attach.fileName + "</span>";
str += "<button type='button' data-file=\'" + fileCallPath + "\' data-type='image' "
str += "class='btn btn-warning btn-circle'><i class='fa fa-times'></i></button><br>";
str += "<img src='${contextPath}/display?fileName=" + fileCallPath + "'>";
str += "</div>";
str +"</li>";
} else {
str += "<li data-path='" + attach.uploadPath + "' data-uuid='" + attach.uuid + "' "
str += "data-filename='" + attach.fileName + "' data-type='" + attach.filetype + "' ><div>";
str += "<span> "+ attach.fileName + "</span><br/>";
str += "<button type='button' data-file=\'" + fileCallPath + "\' data-type='file' "
str += " class='btn btn-warning btn-circle'><i class='fa fa-times'></i></button><br>";
str += "<img src='${contextPath}/resources/img/attach.png'></a>";
str += "</div>";
str +"</li>";
}
});
$(".uploadResult ul").html(str);
});//end getjson
})();//end function
$(".uploadResult").on("click", "button", function(e){
console.log("delete file");
if(confirm("Remove this file? ")){
var targetLi = $(this).closest("li");
targetLi.remove();
}
});
var regex = new RegExp("(.*?)\.(exe|sh|zip|alz)$");
var maxSize = 5242880; //5MB
function checkExtension(fileName, fileSize){
if(fileSize >= maxSize){
alert("파일 사이즈 초과");
return false;
}
if(regex.test(fileName)){
alert("해당 종류의 파일은 업로드할 수 없습니다.");
return false;
}
return true;
}
$("input[type='file']").change(function(e){
var formData = new FormData();
var inputFile = $("input[name='uploadFile']");
var files = inputFile[0].files;
for(var i = 0; i < files.length; i++){
if(!checkExtension(files[i].name, files[i].size) ){
return false;
}
formData.append("uploadFile", files[i]);
}
$.ajax({
url: "${contextPath}/uploadAjaxAction",
processData: false,
contentType: false,data:
formData,type: "POST",
dataType:"json",
success: function(result){
console.log(result);
showUploadResult(result);
}
}); //$.ajax
});
function showUploadResult(uploadResultArr){
if(!uploadResultArr || uploadResultArr.length == 0){ return; }
var uploadUL = $(".uploadResult ul");
var str ="";
$(uploadResultArr).each(function(i, obj){
if(obj.image){
var fileCallPath = encodeURIComponent(obj.uploadPath + "/s_"+obj.uuid + "_" + obj.fileName);
str += "<li data-path='" + obj.uploadPath + "'";
str +=" data-uuid='" + obj.uuid + "' data-filename='" + obj.fileName + "' data-type='" + obj.image + "'"
str +" ><div>";
str += "<span> "+ obj.fileName + "</span>";
str += "<button type='button' data-file=\'" + fileCallPath + "\' "
str += "data-type='image' class='btn btn-warning btn-circle'><i class='fa fa-times'></i></button><br>";
str += "<img src='${contextPath}/display?fileName=" + fileCallPath + "'>";
str += "</div>";
str +"</li>";
}else{
var fileCallPath = encodeURIComponent(obj.uploadPath + "/" + obj.uuid + "_" + obj.fileName);
var fileLink = fileCallPath.replace(new RegExp(/\\/g),"/");
str += "<li "
str += "data-path='" + obj.uploadPath + "' data-uuid='" + obj.uuid+"' data-filename='" + obj.fileName + "' data-type='" + obj.image + "' ><div>";
str += "<span> " + obj.fileName + "</span>";
str += "<button type='button' data-file=\'" + fileCallPath + "\' data-type='file' "
str += "class='btn btn-warning btn-circle'><i class='fa fa-times'></i></button><br>";
str += "<img src='${contextPath}/resources/img/attach.png'></a>";
str += "</div>";
str +"</li>";
}
});
uploadUL.append(str);
}
});
</script>
<%@include file="../includes/footer.jsp"%>
'Programming > Spring' 카테고리의 다른 글
[STS3] 댓글 기능(4) (0) | 2024.04.24 |
---|---|
[STS3] 트랜잭션 (0) | 2024.04.24 |
[STS3] 댓글 기능(3) (0) | 2024.04.23 |
[STS3] 댓글 기능(2) (0) | 2024.04.22 |
[STS3] 댓글 기능(1) (0) | 2024.04.22 |