multipartFile과 application/json 동시에 보내는 방법

개발하는 구황작물·2023년 12월 7일
0

회사 프로젝트

목록 보기
7/8
post-custom-banner

회사에서 프로젝트 도중 이미지를 받아 업로드를 했어야 했다.

문제는 이미지와 dto(application/json) 을 동시에 받아서 처리를 해야 한다는 것이었다.

1. application/json 저장 후 multipartFile 추가하는 방법

처음에는 먼저 application/json 을 받고 저장 후 response로 PK 값을 다시 프론트에서 보내면 다시 프론트에서 PK 값과 이미지를 백엔드로 던져주는 방식으로 진행했다.

그러나 api를 두번 전달하는 것은 비효율적이라 생각했다.

2. multipart/form-data와 application/json 동시에 받는 방법

백엔드에서 동시에 받는 방법은 의외로 간단하다
@RequestPart 로 각각 MultipartFile과 DTO를 받으면 된다.

    @PostMapping
    public ResponseEntity<ResponseDto<?>> createEdgeDevice(@RequestPart(value = "request") ARequestDto request,
                                                           @RequestPart(value = "file", required = false) MultipartFile file) {


        int aId = AService.createA(request, file);
        return ResponseEntity.ok()
                .body(ResponseDto.builder()
                        .code("200")
                        .message("SUCCESS")
                        .data(aId)
                        .build());
    }

💡@RequestPart
“multipart/form-data” 요청의 일부를 메소드 인수와 연결하는 데 사용할 수 있는 어노테이션이다. MultipartFile 형식의 파라미터가 들어오면 MultipartFileResolver를 통해 역직렬화를 하게 되고, 만약 메소드 파라미터 타입이 “multipart/form-data” 외의 다른 타입이라면 Request Headers의 Content-type를 고려하여 HttpMessageConverter를 거치게 된다고 한다. 이는 @RequestBody와 유사한 방식이다.

문제는 프론트엔드에서 텍스트와 이미지를 동시에 보내야 했는데 Headers 에 Content-type는 하나만 설정이 가능하다는 것이었다.

다행히 http에서는 Content-type을 multipart으로 설정하면 두가지 이상의 타입을 사용할 수 있다.

const files = this.fileList; //file 목록
const data = {
	name: "name",
  	grade: 3
}

const formData = new FormData();
const json = JSON.stringify(data);
const blob = new Blob([json], { type: 'application/json' });

formData.append("data", blob);

for(let i = 0; i<files.length; i++) {
 	formData.append("multipart", files[i]); 
}

try {
	const res = await.axios.post('url', formData, {
        headers: {
            'Content-Type': 'multipart/form-data'
          {
    });
} catch (error) {
	console.error("error:", error);
}

위와 같이 텍스트는 Blob에 넣고 이미지와 함께 formData에 넣어 content-type를 multipart/form-data로 설정해주니 성공하였다.

profile
어쩌다보니 개발하게 된 구황작물
post-custom-banner

0개의 댓글