[Spring] Swagger에서 @ReqeustPart를 사용하여 MultiPartFile과 DTO 처리 시 Content type 'application/octet-stream' not supported 오류 해결

오형상·2023년 7월 25일
3

RecipeFriend

목록 보기
4/8
post-thumbnail

현재 상황

저번에 작성했던 @RequestPart를 이용한 MultipartFile, DTO 처리을 통해 postman으로 테스트 결과 정상적으로 작동하였으나 Swagger에서 테스트시 오류가 발생하여 Swagger에서도 정상 작동하도록 수정하려고 한다.

ItemController

@ReqeustPart + @ReqeustPart로 DTO와 MultipartFile을 받고
cosumes을 통해 미디어 타입(또는 Content-Type)을 지정하였습니다.

@Slf4j
@RestController
@RequiredArgsConstructor
@RequestMapping("/api/v1/items")
@Tag(name = "Item", description = "품목 API")
public class ItemController {

    private final ItemService itemService;

    @Operation(summary = "품목 추가")
    @PostMapping(consumes = {MediaType.MULTIPART_FORM_DATA_VALUE})
    public Response<ItemDto> createItem(@RequestPart ItemCreateRequest request, @RequestPart MultipartFile multipartFile, Authentication authentication) {

        ItemDto response = itemService.saveItem(request, multipartFile);

        return Response.success(response);
    }
}

Swagger

현재 상황에서 스웨거를 실행하면 415에러를 발생합니다.

로그를 보면 아래의 에러와 같습니다.

2023-07-25T09:48:03.820+09:00  WARN 13624 --- [nio-8080-exec-1] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.web.HttpMediaTypeNotSupportedException: Content-Type 'application/octet-stream' is not supported]

해결

Custom converter 생성

이 클래스는 AbstractJackson2HttpMessageConverter를 상속하고, "Content-Type: multipart/form-data" 헤더를 지원하는 HTTP 요청의 처리를 위한 용도로 설계되었습니다.

MultipartJackson2HttpMessageConverter 클래스는 ObjectMapper 객체를 생성자로 받아들입니다. 이 ObjectMapper는 JSON 데이터와 Java 객체 간의 변환을 담당하는 Spring의 기본 JSON 라이브러리입니다.

또한, 해당 클래스에서는 HTTP 응답 출력을 지원하지 않도록 canWrite() 메서드들을 오버라이드하여 모두 false를 반환하도록 설정되어 있습니다. 이로 인해 이 메시지 컨버터는 주로 HTTP 요청 데이터를 객체로 변환하는 데 사용됩니다.

위 코드를 Spring 프로젝트에 추가하고 @Component 어노테이션을 통해 빈으로 등록하면 Spring 컨텍스트에서 이 클래스의 인스턴스가 생성되어 관리됩니다.

@Component
public class MultipartJackson2HttpMessageConverter extends AbstractJackson2HttpMessageConverter {

    /**
     * "Content-Type: multipart/form-data" 헤더를 지원하는 HTTP 요청 변환기
     */
    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;
    }
}

이제 Swagger에서도 아래와 같이 정상적으로 작동한다.


전체코드 보러가기

Reference

2개의 댓글

comment-user-thumbnail
2023년 7월 25일

유익한 글이었습니다.

답글 달기
comment-user-thumbnail
2024년 1월 23일

List... 도 정상작동 하나요?

답글 달기