본문 바로가기

Spring/개발

[Spring, Http] Multipart 요청으로 JSON과 파일 한번에 보내기

게시판 같은 걸 구현하다 보면 Dto에 담을 데이터를 담은 JSON형태의 문자열과 사진, 동영상 같은 파일을 전송해야 할 경우가 있다. 멀티파트 요청을 사용한다면 한 번의 요청으로 모두 전송할 수 있다.

 

요청은 기본적으로 POST이다. 헤더의 Content-Type에 multipart/form-data를 넣어준다.

 

바디의 Key는 서버에서 매칭을 위해 사용할 값이니 원하는 대로 설정하자. Value는 아래처럼 원하는 값이나 파일(여러개도 가능)을 넣어주면 된다. Content-Type도 지정 가능하다.

예시에 사용된 파일명들(아래에 다시 나옴)

 

JSON으로 서버에서 Dto에 요소들을 자동으로 바인딩하고 싶다면 반드시 Content-Type에 application/json을 넣어주자 그렇지 않으면 아래와 비슷한 에러가 발생할 수 있다.

[org.springframework.web.HttpMediaTypeNotSupportedException:
Content-Type 'multipart/form-data;boundary=----WebKitFormBoundaryEnzYm3YGjQtKgLIN' is not supported]

※ 혹시 넣어도 에러가 난다면 Content-Type이 아니라 Description에 추가한 건 아닌지 확인해보자.(경험담 맞음)

 

테스트를 위한 Dto를 간단하게 만들었다.

@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class TestDto {
    String text;
    String name;
}

 

JSON은 Dto에 바인딩 후 확인하고, 파일은 따로 처리하는 Controller의 메서드이다. 바인딩이 제대로 되었다면 로그가 정상적으로 출력될 것이고 파일들은 S3에 업로드되게 만들었다. S3를 다루는 방법은 추후에 업로드할 예정이다.

consumes를 쓰지 않으면 required를 설정해도 없으면 에러가 난다.

@RequestPart를 쓰고 있으니 에러가 난다면 확인하자.

 @PostMapping(value ="/api/media/upload", consumes = "multipart/form-data")
public ResponseEntity<String> uploadFile
            (@RequestPart(value="requestDto") TestDto testDto,
             @RequestPart(value = "files",required = false) MultipartFile[] files)
    {
        try {
            log.info(testDto.toString());
            if(files!=null)
                for(MultipartFile file: files){
                    log.info(s3Service.saveFile(file));
                }
            return ResponseEntity.ok("success");
        } catch (IOException e) {
            log.debug(e.getMessage());
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
        }
    }

 

바인딩이 정상적으로 수행되어 찍힌 로그

 

S3에 파일들이 거의 동시에 업로드된 모습

 

이 포스트에서는 요청의 사용법과 요소들을 잘 분리되어 처리할 수 있다는 것만 보여줬지만 사용 난이도에 비해 활용도가 높은 도구라고 생각합니다.

'Spring > 개발' 카테고리의 다른 글

[Spring] Port 8080 was already in use. 오류 해결 방법  (0) 2024.01.18