저번글의 에디터 적용을 활용해서 비동기 댓글창에도 에디터를 적용해주고 , 에디터를 이용해서 이미지 삽입 및 서버에 저장이 가능하도록 만들었다.
먼저 댓글작성시 파일첨부를 하면 업로드가 될 수 있도록 만든다.
새로 댓글파일첨부 테이블을 만들어서 댓글로직을 따로 처리할 수도 있지만,
여차피 게시글과 같은 로컬에 저장 할 것이고,
댓글PR인 RNO를 댓글을 구현하면서 VO(getter&setter)로 쉽게 받아올 수 있게 만들어놨기 때문에,
게시글과 같은 파일첨부테이블을 사용한다.
먼저 원래의 파일첨부테이블에 RNO (댓글PR)을 추가해준다.
alter table MP_FILE add column RNO number;
!! NULL값을 허용해야 한다. (NOT NULL X)
<insert id="insertReply" parameterType = "kr.co.vo.ReplyVO" keyProperty="rno">
<selectKey keyProperty="rno" resultType="int" order="BEFORE">
SELECT MP_REPLY_SEQ.NEXTVAL FROM DUAL
</selectKey>
INSERT INTO MP_REPLY(
BNO,RNO,CONTENT,WRITER
)VALUES(
#{bno},
#{rno},
#{content},
#{writer}
)
</insert>
우선 전에 작성한 첨부파일 업로드와 동일한 방식으로 구현했다.
다른점은 일단 게시글작성의 첨부파일은 bno(게시글PR)이 없기 때문에 selectkey가 bno였던 반면,
댓글은 이미 작성된 글에서 작성하기 때문에 bno는 당연히 있고,
rno로 파일을 구분할 것이기 때문에, selectkey로 rno를 먼저 만들어준다.
public List<Map<String, Object>> parseInsertFileInfoReply(ReplyVO replyVO,
MultipartHttpServletRequest mpRequest) throws Exception{
Iterator<String> iterator = mpRequest.getFileNames();
MultipartFile multipartFile = null;
String originalFileName = null;
String originalFileExtension = null;
String storedFileName = null;
List<Map<String, Object>> list = new ArrayList<Map<String,Object>>();
Map<String, Object> listMap = null;
int bno = replyVO.getBno();
int rno = replyVO.getRno();
File file = new File(filePath);
if(file.exists() == false) {
file.mkdirs();
}
while(iterator.hasNext()) {
multipartFile = mpRequest.getFile(iterator.next());
if(multipartFile.isEmpty() == false) {
originalFileName = multipartFile.getOriginalFilename();
originalFileExtension = originalFileName.substring(originalFileName.lastIndexOf("."));
storedFileName = getRandomString() + originalFileExtension;
file = new File(filePath + storedFileName);
multipartFile.transferTo(file);
listMap = new HashMap<String, Object>();
listMap.put("BNO", bno);
listMap.put("RNO", rno);
listMap.put("ORG_FILE_NAME", originalFileName);
listMap.put("STORED_FILE_NAME", storedFileName);
listMap.put("FILE_SIZE", multipartFile.getSize());
list.add(listMap);
}
}
return list;
}
게시글작성에서 첨부파일을 구현할때 작성해놓은 FileUtils.java를 활용하려고 한다.
파일관련한 파라미터들을 처리하는 로직을 따로 컴포넌트로 구현해놨다.
클래스명을 변경해주고, 매개변수는 원래 게시글에 필요한 VO인 BoardVO였던 부분을 댓글의 VO인 ReplyVO로 바꿔준다. Multipart 인터페이스는 당연히 그대로 넣어준다.
게시글 첨부파일 insert에는 bno만 있으면 되지만,
댓글 첨부파일insert에는 bno와 rno가 필요하기 때문에 (새로 댓글파일테이블을 만들면 rno만 있어도 되지만 원래의 파일테이블에 들어가기 때문에 NOT NULL 설정을 해놓은 컬럼인 bno가 필요하다 )
원래의 list.put에 rno만 더 들어가면 되기 때문에, getRno로 vo에서 값을 가져와주고, put으로 map에 rno를 넣어준다
DAO
public void insertFileReply(Map<String, Object> map) throws Exception;
public void insertFileReply(Map<String, Object> map) throws Exception{
sql.insert("replyMapper.insertFileReply", map);
}
sqlsession으로 Mapper위치를 지정하고 파라미터를 넣어준다.
Service
@Transactional
@Override
public void writeReply(ReplyVO vo,MultipartHttpServletRequest mpRequest) throws Exception {
dao.writeReply(vo);
daoo.replyCount(vo.getBno());
List<Map<String,Object>> list = fileUtils.parseInsertFileInfoReply(vo,mpRequest);
int size = list.size();
for(int i=0; i<size; i++) {
dao.insertFileReply(list.get(i));
}
}
글작성 service 부분에 dao.insertFileReply을 넣어준다.
사실 for문고 List는 다중파일작성을 위해 필요한 부분인데, 난 댓글에는 하나의 사진(파일)만 올릴 수 있게 만들 계획이라 이렇게 만들 필요가 없지만 게시글 첨부파일 로직을 그대로 가져와 쓰다보니 ...
다음에는 단일파일작성을 구성해보겠다. 더 간단하다.
Controller
@RequestMapping(value = "/writeReply")
public void writeReply(ReplyVO vo,MultipartHttpServletRequest mpRequest)throws Exception{
logger.info("writeReply");
logger.info("mpRequest=" + mpRequest);
replyService.writeReply(vo,mpRequest);
댓글작성 컨트롤러 부분에서 파일의 Multipart인코딩 값을 받을 수 있도록 매개변수에 인터페이스를 넣어주고,
service에 파라미터를 넘겨준다.
vo - rno와 bno
mpRequest - 파일업로드,다운로드에 필요한 파일이름,사이즈 등등이 담겨있는 값
(Multipart라이브러리의 인터페이스로 multipart값을 받으면 mpRequest.getFileNames 등으로
파일의 파라미터를 얻을 수 있다)
그 다음 게시글내용(상세페이지)의 댓글작성 부분에 에디터를 추가해준다.
에디터 추가는 전 글에 적어놓았다.
summernote 에디터를 사용하면 간편하게 이미지 추가를 할 수 있고 ,
댓글창에도 이미지가 잘 온다...
사실 위의 첨부파일 로직은 상관이 없이, 이미지 data를 content의 데이터베이스에 data img 형식으로
이미지를 코드화 시켜서 데이터베이스 자체에 저장한다.
첨부파일은 로컬저장소를 따로 만들고, 그 위치에 대한 정보만 데이터베이스에 저장한 후 보통 그 첨부파일을 호출하면 로컬저장소에서 꺼내서 사용하는데 그 이유는 데이터베이스 자체에 이미지를 저장하면 용량이 감당이 안될뿐만 아니라 서버에 부하가 많이가서 느려진다..
에디터에서 이미지 업로드 후 content를 select 해보면 정말 엄청엄청나게 코드가 길다...
에디터로 이미지를 추가해도 그 data가 컨트롤러에 multipart 인코딩타입으로 넘어오면 따로 로컬저장소에 저장되게 해놔서 로컬에 에디터로 추가한 이미지가 넘어오긴 하나.. 여기서 끝내는 방법은 이상적인 방법이 아니다.
그래서 에디터에서 콜백함수를 사용해서 이미지를 로컬에서 꺼내오는 방법이 있고,
rno로 저장된 파일이름을 조회해서 resources mapping으로 경로설정 후 img src로 올리는 방법도 있겠다.
근데 아직 ajax에 대한 이해가 완전하지 않아서 구현을 못하겠다 ;;;
할수는 있을 것 같은데 너무 시간이 오래 걸릴 것 같다..
그래서 이 부분은 나중에 이미지 업로드가 중요한 쇼핑몰 구현에서 한번 자세히 다뤄보려고 한다.
일단 구현한 부분까지만 설명을 해놓겠다.
댓글작성 form태그 부분에 enctype="multipart/form-data"을 추가해주고,
ajax에서 입력한 댓글의 insert값을 받는 부분에서
var insertData = new FormData($('#commentInsertForm')[0]);
commentInsert(insertData);
데이터가 json이 아닌 FormData로 넘어갈 수 있도록
new = FormData($('insert값')[0]) 을 해준다.
이걸 해주지않으면 multipart값이 넘어가지 않는다.
그 이유는 contentType이 json인데 , multipart도 contentType이고 이것은 두개가 같이 넘어갈 수 없어서
데이터 form값으로 넘어가도록 설정해줘야 multipart값이 넘어가서 파일 업로드를 할 수 있다.
다음 프로젝트에선 ajax형식에서 첨부파일을 넣고 빼고, 에디터에 콜백함수를 적용해보도록 하겠다..
또 , 에디터를 적용하다보니 글 내용에 html 태그가 붙는다.
그 때문에 ajax 댓글내용 조회 부분에서 html태그가 내용에 따라 침범해서 댓글창이 엉망이 될 때가 있다.(특히 이미지파일을 content내용으로 올릴때)
스크립팅을 막는 방법도 찾아봤으나 역시 ajax에선 후.........
아직 실력이 정말 많이 부족하다고 느껴진다ㅜㅜ
다음 프로젝트에선 ajax 특훈을 하고 접근해야겠다고 뼈저리게 생각한다.
'SPRING > IceWater Community' 카테고리의 다른 글
[스프링] 다중 게시판 구현 (CRUD) (1) | 2021.09.06 |
---|---|
[스프링]게시판 이전글 다음글 구현 (5) | 2021.09.03 |
[스프링]게시판 글작성 에디터 적용과 파일미리보기,이미지 미리보기 (0) | 2021.08.30 |
[스프링] 첨부파일 다중파일 구현, 수정,삭제 로직의 설명(4) (2) | 2021.08.30 |
[스프링]게시판 첨부파일 다운로드 (3) (1) | 2021.08.30 |