TIL) Content type 'application/octet-stream' not supported 에러
by Won's log2023. 9. 13.
상황 : 프런트에서 AWS S3를 이용하여 게시물에 이미지를 업로드하고 생성할 때 백엔드에 게시물의 데이터를 전달하는 상황
에러 상황: Content type 'application/octet-stream' not supported 에러
DefaultHandlerExceptionResolver : Resolved [org.springframework.web.HttpMediaTypeNotSupportedException: Content-Type 'application/octet-stream' is not supported]
에러 이유: SpringBoot Controller의 핸들러 메서드에서 게시글에 필요한 requestDto 데이터와 이미지 저장을 위한 MultipartFile을 함께 사용시 발생한 오류
포스트맨으로 사전 테스트 시, form-data 타입을 사용하여 이미지는 multipart/form-data으로, dto 데이터는 parameter에 담아 보내서 성공적으로 데이터를 전달하였다.
그러나 프런트에서 ajax를 사용하여 백에 데이터를 전달할 때 Content-Type을 인식할 수 없어서 오류가 발생했고 이미지와 dto 데이터를 전달할 수 있도록 수정이 필요했다.
시도 : image는 content type이 multipart/form-data 이고 dto는 content type이 application/json이기 때문에 contentType을 “contentType: false, *// Content-Type 자동 설정 비활성화”*로 고쳤으나 여전히 문제가 같았다.
수정사항 : ajax에 데이터를 보내야하는 값은 하나였으나 image는 content type이 multipart/form-data 이고 dto는 content type이 application/json이기 때문에 둘을 합치는 로직이 필요했다. 그래서 이미지 업로드를 위한 imageFormData와 데이터를 JSON 형식으로 변환한 후 Blob으로 감싼 jsonDataBlob을 따로 생성했다. 그런 다음, 두 개의FormData객체를 합쳐서 formData에 추가하고 서버로 전송하였다. 이렇게 하면 이미지와 데이터를 각각 올바른 Content-Type으로 서버에 전송할 수 있게 되었고 결론적으로 게시물에 이미지가 잘 올라간 것을 확인할 수 있었다.
$(document).ready(function () {
$('#savePost').click(function () {
const title = $('#title').val();
const category_id = $('#category').val();
const content = $('#content').val();
const imageFile = $('#image')[0].files[0];
// 파일 크기 확인 (1MB 이상인 경우 처리)
if (imageFile && imageFile.size > 1048576) { // 1MB 이상인 경우
alert("파일 크기가 너무 큽니다. 1MB 보다 작은 파일을 선택해주세요.");
return; // 업로드 중단
}
// 이미지 업로드를 위한 FormData 객체 생성
const imageFormData = new FormData();
imageFormData.append('image', imageFile);
// 데이터를 JSON 형식으로 생성
const jsonData = {
title: title,
category_id: category_id,
content: content
};
// JSON 데이터를 문자열로 변환한 후 Blob으로 감싸기
const jsonDataBlob = new Blob([JSON.stringify(jsonData)], { type: 'application/json' });
// FormData 객체 생성하고 JSON 데이터 추가
const dataFormData = new FormData();
dataFormData.append('data', jsonDataBlob);
// 두 개의 FormData 객체를 합치기
const formData = new FormData();
formData.append('image', imageFile);
formData.append('data', jsonDataBlob);
// 서버로 데이터 전송 (Ajax)
$.ajax({
type: 'POST',
url: '/api/post',
data: formData,
contentType: false, // Content-Type 자동 설정 비활성화
processData: false, // 데이터 처리 비활성화
success: function (response) {
// 성공 처리
alert(response.message);
window.location.href = '/view/posts';
},
error: function () {
// 오류 처리
alert('게시글 등록이 실패하였습니다');
}
});
});
});