Summer Note
- 부트스트랩과 함께 게시판 글 작성 기능에 디자인 기능 및 편의를 제공하는 라이브러리
- 특히 파일을 추가해야 하는 경우에 유용
- SQL에서 contents를 받는 컬럼을 clob으로 설정해야 한다 (자료 그 자체로 저장됨).
jsp 단
- ajax 부분에서 ....
contentType:false
의 의미는 인코딩이 multipart/form-data라는 것이다. (디폴트가 true
=> enctype="x-www-form-urlencoded")
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>섬머노트</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Lato:wght@100;300;400;700;900&family=Noto+Sans+KR:wght@100;300;400;500;700;900&display=swap" rel="stylesheet">
<link rel="stylesheet" href="../css/reset.css">
<link rel="stylesheet" href="../css/common.css">
<link rel="stylesheet" href="../css/layout.css">
<script src="../js/jquery-3.6.3.min.js"></script>
<link href="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">
<script src="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js"></script>
<script src="//t1.daumcdn.net/mapjsapi/bundle/postcode/prod/postcode.v2.js"></script>
<link href="../summernote/summernote.min.css" rel="stylesheet">
<script src="../summernote/summernote.min.js"></script>
</head>
<body>
<header id="header" class="header">
<h1 id="logo">
<a href="index.jsp">JJANG'S MEDIA LAB</a>
</h1>
<nav id="gnb">
<h2 class="hidden">global navigation</h2>
<ul class="list">
<li><a href="">회원가입</a></li>
<li><a href="">로그인</a></li>
<li><a href="">게시판</a></li>
</ul>
</nav>
</header>
<main>
<form class="form" action="../board/writeProcess" method="POST">
<table class="board">
<colgroup>
<col style="width:20%">
<col style="width:80%">
</colgroup>
<tbody>
<tr>
<th>이름</th>
<td><input type="text" name="userName"></td>
</tr>
<tr>
<th>내용</th>
<td>
<textarea name="contents" id="summernote"></textarea>
</td>
</tr>
</tbody>
</table>
<div class="btns">
<button class="btn confirm">확인</button>
<button class="btn reset" type="reset">취소</button>
</div>
</form>
</main>
<script>
$("#summernote").summernote({
height:300,
callbacks:{
onImageUpload:function(files) {
console.log("이미지 첨부 됨");
console.log(files);
for(let i=0;i<files.length;i++){
uploadImage(files[i],this);
}
}
}
})
function uploadImage(file,editor) {
const sendData = new FormData();
sendData.append("uploadFile",file);
console.log(sendData);
$.ajax({
url:"../board/summernoteFileUpload",
type:"POST",
data:sendData,
contentType:false,
processData:false,
success:function(response) {
console.log(response);
$(editor).summernote("editor.insertImage",response.fileUrl);
},
error:function() {
console.log("파일 업로드 실패");
}
})
}
</script>
<footer class="footer">
<address>
<p>all copyrights reserved by ----</p>
</address>
</footer>
</body>
</html>
서블릿 단
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.google.gson.Gson;
import com.jjang051.utils.ScriptWriter;
import com.oreilly.servlet.MultipartRequest;
import com.oreilly.servlet.multipart.DefaultFileRenamePolicy;
@WebServlet("/board/summernoteFileUpload")
public class FileUploadController extends HttpServlet {
private static final long serialVersionUID = 1L;
public FileUploadController() {
super();
}
protected void service(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("UTF-8");
int maxFileSize = 1024*1024*50; // 50메가
String encoding = "UTF-8";
DefaultFileRenamePolicy fileRenamePolicy = new DefaultFileRenamePolicy();
String savePath = "summerNoteUpload";// 저장할 폴더 이름
ServletContext context = this.getServletContext();
String realPath = context.getRealPath(savePath);
File dir = new File(realPath);
if(!dir.exists()) {
dir.mkdir();
}
MultipartRequest mutipartRequest =
new MultipartRequest(request, realPath, maxFileSize,
encoding, fileRenamePolicy);
String fileRealName =
mutipartRequest.getFilesystemName("uploadFile"); // 중복된 이름 처리하는 곳
System.out.println(fileRealName);
String fileUploadedUrl =
"/jsp10_board_summernote/"+savePath+"/"+fileRealName;
HashMap<String, String> fileUrlMap = new HashMap<>();
fileUrlMap.put("fileUrl",fileUploadedUrl);
Gson gson = new Gson();
String fileUrl = gson.toJson(fileUrlMap);
request.setAttribute("fileUrl", fileUrl);
RequestDispatcher dispatcher =
request.getRequestDispatcher("/WEB-INF/board/summernoteFileUpload.jsp");
dispatcher.forward(request, response);
//json으로 응답예정
}
}
서블릿의 response를 받는 jsp
<%@ page language="java" contentType="application/json; charset=UTF-8"
pageEncoding="UTF-8"%>
${fileUrl }
- 서블릿이 날리는 request는 이미지가 저장된 파일 경로에 관련한다.
- 그 요청을 이 jsp가 받아 response에 띄우면 앞서 wrtie단의 jsp에 있는 ajax의 success부분이 response를 처리하여, 이미지를 화면에 띄울 수 있게 된다.