1. 이슈사항
- DefaultHandlerExceptionResolver 발생
- JSON으로 파싱할때 타입이 안맞아서 생기는 에러로 보임(VALUE_STRING token)
WARN 10900 --- [nio-8989-exec-7] .w.s.m.s.DefaultHandlerExceptionResolver
: Resolved [org.springframework.http.converter.HttpMessageNotReadableException
: JSON parse error
: Cannot deserialize instance of `[Lorg.springframework.web.multipart.MultipartFile;` out of VALUE_STRING token;
nested exception is com.fasterxml.jackson.databind.exc.MismatchedInputException
: Cannot deserialize instance of `[Lorg.springframework.web.multipart.MultipartFile;` out of VALUE_STRING token
at [Source: (PushbackInputStream); line: 1, column: 106] (through reference chain: edu.bit.ex.joinvo.BoardImageUploadVO["uploadfiles"])]
2. 해결사항
2-1. VIew 페이지에서 AJAX 처리시 Type 파라미터를 FormData로 변경(JSON.stringify => FormData)
$.ajax({
dataType: 'json',
type : "POST",
url : $(this).attr("action"),
cache : false,
contentType:'application/json; charset=utf-8',
processData: false,
data: JSON.stringify({form, formData}),
success: function (result) {
$(location).attr('href', '${pageContext.request.contextPath}/board/magazine')
},
error: function (e) {
console.log(e);
alert('업로드를 할 수 없습니다.');
location.reload();
}
});
$.ajax({
type : "POST",
url : $(this).attr("action"),
cache : false,
contentType:'application/json; charset=utf-8',
processData: false,
contentType: false,
data: formData,
success: function (result) {
$(location).attr('href', '${pageContext.request.contextPath}/board/magazine');
},
error: function (e) {
console.log(e);
alert('업로드 실패');
location.reload();
}
});
2-2. JSON.stringify()로 받지 않는다는건 말그대로 문자 형태의 데이터를 넘기지 않는다는 의미이므로 Controller단에 있는 파라미터의 @RequestBody 어노테이션을 달아줄 필요가 없다.
@Transactional
@PostMapping("/magazine/write")
public ResponseEntity<String> magazineWrite(BoardPrdctImageVO bPrdctImageVO) {
ResponseEntity<String> entity = null;
log.info("magazineWrite..");
MultipartFile[] uploadfiles = bPrdctImageVO.getUploadfiles();
try {
boardService.setMagazineWrite(bPrdctImageVO);
for (MultipartFile f : uploadfiles) {
boardService.setMagazineImage(f);
}
entity = new ResponseEntity<String>("SUCCESS", HttpStatus.OK);
} catch (Exception e) {
e.printStackTrace();
entity = new ResponseEntity<String>(e.getMessage(), HttpStatus.BAD_REQUEST);
} return entity;
}
3. JSP파일
<script>
$(document).ready(function () {
$("#writeForm").submit(function(event){
event.preventDefault();
var formData = new FormData();
var mbr_id = $("#mbr_id").val();
var board_name = $("#board_name").val();
var board_content = $("#board_content").val();
console.log(mbr_id);
console.log(board_name);
console.log(board_content);
console.log($(this).attr("action"));
formData.append("mbr_id", mbr_id);
formData.append("board_name", board_name);
formData.append("board_content", board_content);
var inputFile = $("#uploadfiles");
var files = inputFile[0].files;
for (var i = 0; i < files.length; i++) {
console.log(files[i]);
formData.append("uploadfiles", files[i]);
}
$.ajax({
type : "POST",
url : $(this).attr("action"),
cache : false,
contentType:'application/json; charset=utf-8',
processData: false,
contentType: false,
data: formData,
success: function (result) {
console.log("UPLOAD SUCCESS!")
$(location).attr('href', '${pageContext.request.contextPath}/board/magazine');
},
error: function (e) {
console.log(e);
alert('업로드 실패');
location.reload();
}
})
});
})
</script>
<form id="writeForm" method="post" action="${pageContext.request.contextPath}/board/magazine/write" enctype="multipart/form-data">
<input type="hidden" id="mbr_id" value="${magazine_write.mbr_id}">
<input class="form-control" type="text" id="board_name" name="board_name" placeholder="글제목을 입력하세요">
<textarea class="form-control" cols="3" id="board_content" name="board_content" placeholder="글내용을 입력하세요"></textarea>
<input type="file" id="uploadfiles" name="uploadfiles" placeholder="첨부 사진" multiple/>
<button type="submit" class="btn btn-primary">작성하기</button>
</form>
4 . Controller
@Transactional
@PostMapping("/magazine/write")
public ResponseEntity<String> magazineWrite(BoardPrdctImageVO bPrdctImageVO) {
ResponseEntity<String> entity = null;
log.info("magazineWrite..");
MultipartFile[] uploadfiles = bPrdctImageVO.getUploadfiles();
try {
boardService.setMagazineWrite(bPrdctImageVO);
for (MultipartFile f : uploadfiles) {
boardService.setMagazineImage(f);
}
entity = new ResponseEntity<String>("SUCCESS", HttpStatus.OK);
} catch (Exception e) {
e.printStackTrace();
entity = new ResponseEntity<String>(e.getMessage(), HttpStatus.BAD_REQUEST);
}
return entity;
}
5. Service
public void setMagazineWrite(BoardVO boardVO);
public void setMagazineImage(MultipartFile file);
@Override
public void setMagazineWrite(BoardVO boardVO) {
log.info("setMagazineWrite");
boardMapper.setMagazineWrite(boardVO);
}
@Override
public void setMagazineImage(MultipartFile file) {
UUID uuid = UUID.randomUUID();
String saveName = uuid + "_" + file.getOriginalFilename();
log.info("image_name: ", saveName);
File saveFile = new File(UPLOAD_PATH, saveName);
try {
file.transferTo(saveFile);
} catch (IOException e) {
e.printStackTrace();
}
boardMapper.setMagazineImage(saveName);
}
6. Mapper
public void setMagazineWrite(BoardVO boardVO);
public void setMagazineImage(String saveName);
<insert id="setMagazineWrite" >
<![CDATA[
INSERT INTO board (board_id, board_name, board_content, mbr_id, board_type_number, board_like, board_hit)
VALUES (board_seq.nextval, #{board_name}, #{board_content}, #{mbr_id}, 2, 0, 0)
]]>
</insert>
<insert id="setMagazineImage" >
<![CDATA[
INSERT INTO prdct_image (image_number, image_name, image_path, board_id)
VALUES (prdct_image_seq.nextval, #{uploadfiles}, 'D:/Others/Programming/Project Space/branches/branches_project/src/main/resources/static/prdct_img/', board_seq.currval)
]]>
</insert>
7. VO
@AllArgsConstructor
@NoArgsConstructor
@Setter
@Getter
@ToString
public class BoardPrdctImageVO {
private String board_name;
private String board_content;
private String mbr_id;
private int board_type_number;
private int inquiry_number;
private Date board_date;
private String prdct_id;
private int order_number;
private int board_like;
private int board_hit;
private int board_starrate;
private int board_id;
private int image_number;
private String image_name;
private String image_path;
private MultipartFile[] uploadfiles;
}
최근댓글