Spring RestTemplate로 multipart/form-data 전송하기

KHS·2022년 9월 5일
0

trouble shooting

목록 보기
2/3
post-thumbnail

요건

  • 화면에서 전달 받은 압축파일을 해제
  • 해제한 파일 중 하나를 다른 서버의 API로 전송
    • 상대 시스템은 Python 3.8, FastAPI로 구성됨
    • Parameter는 Binary 파일, String으로 구성
    • Content-Type은 multipart/form-data

테스트 코드

MultiValueMap<String, Object> params = new LinkedMultiValueMap<>();
params.add("파라미터1", new ByteArrayResource(파일 내용 byte[]));
params.add("파라미터2", "문자열 값");

HttpHeaders uploadheaders = new HttpHeaders();
uploadheaders.setContentType(MediaType.MULTIPART_FORM_DATA);

HttpEntity<?> uploadEntity = new HttpEntity<>(params, uploadheaders);

RestTemplate restTemplate = new RestTemplate();

ResponseEntity<SttCommonResultResponseDto> responseEntity = restTemplate.exchange(
  requestUrl,
  HttpMethod.POST,
  uploadEntity,
  SttCommonResultResponseDto.class
);

1차 실행 결과

  • 디버그 로그(해당 코드에서는 파라미터2는 전송하지 않음, 비필수 값)
15:51:45.985 [main] DEBUG org.springframework.web.client.RestTemplate - Accept=[application/json, application/*+json]
15:51:45.998 [main] DEBUG org.springframework.web.client.RestTemplate - Writing [{파라미터1=[Byte array resource [resource loaded from byte array]]}] as "multipart/form-data"
15:52:50.949 [main] DEBUG org.springframework.web.client.RestTemplate - Response 422 UNPROCESSABLE_ENTITY
  • 에러 로그
{
    "detail": [{
            "loc": ["body", "파라미터1"],
            "msg": "Expected UploadFile, received: [class 'str']",
            "type": "value_error"
        }
    ]
}

원인 분석(불확실함)

  • multipart 업로드는 로컬 파일을 업로드 하는데 사용하는 방식
  • new ByteArrayResource()를 RestTemplate의 파라미터로 설정 시 파일에 대한 정보가 없어 메모리 상의 데이터를 전송함
  • 파일 메타데이터 없이 byte 배열만 전송하여 FastAPI에서 String으로 인식하게 되는 것이 원인인 것으로 판단됨

변경 코드

Path path = Paths.get("Uuid 임시 파일 위치");

MultiValueMap<String, Object> params = new LinkedMultiValueMap<>();
params.add("파라미터1", new PathResource(path));
params.add("파라미터2", "문자열 값");

HttpHeaders uploadheaders = new HttpHeaders();
uploadheaders.setContentType(MediaType.MULTIPART_FORM_DATA);

HttpEntity<?> uploadEntity = new HttpEntity<>(params, uploadheaders);

RestTemplate restTemplate = new RestTemplate();

ResponseEntity<SttCommonResultResponseDto> responseEntity = restTemplate.exchange(
  requestUrl,
  HttpMethod.POST,
  uploadEntity,
  SttCommonResultResponseDto.class
);

2차 실행 결과

  • 디버그 로그(해당 코드에서는 파라미터2는 전송하지 않음, 비필수 값)
16:25:10.079 [main] DEBUG org.springframework.web.client.RestTemplate - Accept=[application/json, application/*+json]
16:25:10.087 [main] DEBUG org.springframework.web.client.RestTemplate - Writing [{파라미터1=[path [Uuid 임시 파일 위치]]}] as "multipart/form-data"
16:25:38.558 [main] DEBUG org.springframework.web.client.RestTemplate - Response 200 OK

정리

  • Python FastAPI와 통신할 때 multipart/form-data 전송 시 byte 배열을 전송하면 타입 오류가 발생할 수 있음
  • In-Memory 데이터로 전송하지 않고 임시 파일을 생성해 전송하는 방식을 사용하면 타입 오류를 방지할 수 있음
  • 임시 파일 생성 방식을 사용할 때 Disk Full 이슈를 방지하기 위해 주기적 삭제 혹은 작업 완료 후 삭제 같은 정책이 있어야 함
profile
Java & Vue ...

0개의 댓글