반응형
controller
/**
* 게시글 등록 처리(비동기)
* @param boardVo
* @param files
* @return
*/
@PostMapping(value = "/regAjax")
@ResponseBody
public Integer regAjax(@RequestPart(value = "boardVo") BoardVo boardVo,
@RequestPart(value = "files", required = false) List<MultipartFile> files,
HttpSession session) throws IOException, Exception {
//테스트니까 try catch로 예외처리 하지 않고 그냥 throws로 던졌다.
UserVo userInfo = getUserSessionInfo(session);
boardVo.setUserId(userInfo.getUserId());
//사실 컨트롤러에서는 서비스 하나만 호출하고 그 서비스에서 게시글 등록, 파일 저장까지 처리하는게 좋다.
boardService.regBoard(boardVo);
fileService.saveFile(files, boardVo.getBoardNo());
return boardVo.getBoardNo();
}
service
/**
* 첨부파일 저장
* @param files
* @param boardNo
*/
@Transactional
public void saveFile(List<MultipartFile> files, Integer boardNo) throws IOException, Exception {
if (!files.isEmpty()) {
FileVo fileVo;
for (MultipartFile file : files) {
//원본파일명
String fileOrgName = file.getOriginalFilename();
//파일 UUID
String fileUUid = UUID.randomUUID().toString();
//파일 확장자
String extension = fileOrgName.substring(fileOrgName.lastIndexOf("."));
//서버에 저장될 파일명(UUID+확장자)
String saveFileName = fileUUid + extension;
//파일 저장 경로
String filePath = this.filePath + saveFileName;
//파일 서버 저장
file.transferTo(new File(filePath));
//파일정보 DB 저장
fileVo = new FileVo();
fileVo.setBoardNo(boardNo);
fileVo.setFileOrgName(fileOrgName);
fileVo.setFilePath(filePath);
fileVo.setFileSize((int) file.getSize());
fileMapper.insertFile(fileVo);
}
}
}
javascript
//게시글 작성(ajax)
$("#regAjax").on("click", function () {
if (!confirm("게시글 등록 할거야(ajax)?")) {
return;
} else {
//form 객체 가져와서 새로 생성(기존에 enctype="multipart/form-data"로 되어 있는 form 객체를 가져옴)
const frm = $("#regFrm")[0];
const formData = new FormData(frm);
//multipartFile 가져옴(<input type="file" class="files" name="files" id="files" multiple="multiple"> multiple 옵션을 줘서 여러개 전송 가능)
let inputFile = $("#files");
//vo에 바인딩 시킬 데이터
const params = {
title: $("#title").val(),
content : $("#content").val()
};
//파일
formData.append("files", inputFile);
//vo
formData.append("boardVo", new Blob([JSON.stringify(params)], {type: "application/json"}));
/*========================================================================================*/
/* 완전 새롭게 formdata 객체를 생성하는 방법은 아래처럼
/*========================================================================================*/
//formdata 새로운 객체 생성
const formData = new FormData();
const params = {
title: $("#title").val(),
content : $("#content").val()
};
//첨부파일
let fileInput = $(".files");
for (var i = 0; i < fileInput.length; i++) {
if (fileInput[i].files.length > 0) {
for (var j = 0; j < fileInput[i].files.length; j++) {
formData.append('files', $('.files')[i].files[j]);
}
}
}
//vo
formData.append("boardVo", new Blob([JSON.stringify(params)], {type: "application/json"}));
/*========================================================================================*/
/* ajax 전송 부분
/*========================================================================================*/
$.ajax({
url : '/regAjax',
type : 'post',
processData: false,
contentType: false,
enctype: "multipart/form-data",
data: formData,
success: function (result) {
alert(result + "번 게시글이 등록되었단다.");
location.href = "/";
},
error: function (request, status, error) {
alert("게시글 등록에 실패했다.");
location.href = "/";
console.log(error);
}
});
}
});
개인적으로 비동기로 json과 multipart 전송 때문에 삽질을 꽤나 많이 해서 기록해 둔다.
테스트 결과 여러개 파일 업로드도 가능하다.
반응형
'IT > development' 카테고리의 다른 글
[springBoot/thymeleaf] ajax 페이지네이션 sample(feat. study용) (2) | 2023.06.04 |
---|---|
[mybatis] mybatis oracle merge into (0) | 2023.06.03 |
[thymeleaf] thymeleaf javascript로 변수 1개 이상 전달 (0) | 2023.05.30 |
[springBoot] 공휴일 조회 API (0) | 2023.05.15 |
[logback] log pattern 설정 (2) | 2023.05.14 |