게시판을 구현하는데 파일업로드를 하는 기능이 있었다.
RequestPart로 구현을 했을 진행을 했고 dto와 multipartFile로 파일과 내용을 받아서 구현을 했다.
@PostMapping(consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public ResponseEntity<BoardResponseDto> createBoard(@RequestPart(value = "dto", required = false) BoardRequestDto boardRequestDto,
@RequestPart(value = "file", required = false) List<MultipartFile> multipartFiles,
@AuthenticationPrincipal CustomUserDetails customUserDetails
) {
BoardResponseDto board = boardService.createBoard(boardRequestDto, customUserDetails.getEmployee(), multipartFiles);
return ResponseEntity.ok(board);
}
controller에서 위에 코드와 같이 구현을 했고
위와 같이 요청을 보냈을 때 업로드와 게시판 등록이 매우 잘 되었다.
그런데 포론트에서 api를 통해서 게시판을 등록할 때 문제가 발생을 했다.
그냥 제목, 내용을 작고 등록을 하면 게시판 등록이 잘 되었지만 파일을 넣고 하면 content-type 에러가 발생을 하였다.
프론트쪽에서 dto는 application/json으로 파일은 multipart로 잘 넣어서 보냈는데도 에러가 발생을 했다.
HttpMessageConverter를 커스텀해서 에러를 해결했다.
알아보니 spring은 기본적으로 multipart 요청, data-form을 처리하는데 MultiPartResolver를 사용을 하는데 이 MultiPartResolver는 텍스트 기반의 메시지 변환만을 지원을 해서 Json이 들어가면 처리하지 못 하는 것이다.
그래서 Custom한 Converter를 만들어서 Json을 따로 추출하는 과정이 필요하다.
package com.github.riset_backend.global.config.uplaod;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.http.MediaType;
import org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter;
import org.springframework.stereotype.Component;
import java.lang.reflect.Type;
@Component
public class MultipartJackson2HttpMessageConverter extends AbstractJackson2HttpMessageConverter {
public MultipartJackson2HttpMessageConverter(ObjectMapper objectMapper) {
super(objectMapper, MediaType.APPLICATION_OCTET_STREAM);
}
@Override
public boolean canWrite(Class<?> clazz, MediaType mediaType) {
return false;
}
@Override
public boolean canWrite(Type type, Class<?> clazz, MediaType mediaType) {
return false;
}
@Override
protected boolean canWrite(MediaType mediaType) {
return false;
}
}
먼저, spring에서 Http를 Json으로 변환을 하는 AbstractJackson2HttpMessageConverter를 상속을 받아서 기능을 확장을 해준다.
AbstractJackson2HttpMessageConverter 상속을 통해서 Json을 파싱하는 기능을 추가해준다.
MultipartJackson2HttpMessageConverter 메소드를 통해서 AbstractJackson2HttpMessageConverter 생성자를 생성을 하고 application/octet-stream을 타입으러 지정을 해주어서 multiPart에서도 Json을 추출을 해서 사용할 수 있도록 해준다.
canWrite 메소드들을 false로 해주어서 읽기만 가능하도록 해준다.
이 방법을 통해서 헤결을 해주었다.
프론트에서도 해보니 multiPart안에 Json을 넣어도 content-type 에러가 발생하지 않고 S3에 업로드도 잘 되었다.