일간에러 2021-12-29

작성: 2021.12.29

수정: 2021.12.29

읽는시간: 00 분

Development/Daily Error

반응형

'append' called on an object that does not implement interface FormData.

문제

image-20211229092606036

jQuery Ajax와 FormData를 이용해 파일을 비동기로 업로드 하던 중 해당 아래와 같은 에러 발생

'append' called on an object that does not implement interface FormData

코드는 다음과 같다.

$('#migration_form').on('submit', function () {
    var formdata = new FormData();
    const file = $('#input_file')[0].files[0];
    formdata.append("file", file);
    event.preventDefault();
    $.ajax({
        url: '{{BASE}}/migration/checkFile',
        type: 'post',
        data: formdata,
    }).done(function (data, status, xhr) {
        console.log('submitAjax', data);
    }).fail(function (xhr, status, error) {
    }).always(function () {
    });
})

분명 new FormData()로 명확하게 FormData를 만들어 줬는데, FormData 인터페이스를 구현하지 않은 객체에서 append 콜이 나왔다는 에러가 참 의아했다.

원인

processData의 옵션이 true일때 ajax에서는 객체로서 data 옵션으로 전달되는 데이터들을 query string으로 변환해 처리하며, application/x-www-form-urlencoded 로 컨텐츠 타입을 맞춘다.

processData의 default 값이 true 이기 때문에, 데이터 처리를 원하지 않는다면 false로 옵션을 바꿔야 한다.

image-20211229093656652

https://api.jquery.com/jQuery.ajax/

또한 contentType 옵션의 기본 설정은 application/x-www-form-urlencoded; charset=UTF-8 이다.

image-20211229093730775

해결

processData를 false로 변경해서 query string으로 처리하지 못하도록 막는다. 또한 contentType을 false로 변경해서 content type header를 설정하지 않도록 해준다.

결론적으로 아래의 두줄이 추가되면 된다.

processData: false,
contentType: false,

수정한 전체 코드는 다음과 같다.

$('#migration_form').on('submit', function () {
    var formdata = new FormData();
    const file = $('#input_file')[0].files[0];
    formdata.append("file", file);
    event.preventDefault();
    $.ajax({
        url: '{{BASE}}/migration/checkFile',
        type: 'post',
        data: formdata,
        processData: false,
        contentType: false,
        cache: false
    }).done(function (data, status, xhr) {
        console.log('submitAjax', data);
    }).fail(function (xhr, status, error) {
    }).always(function () {
    });
})

컨트롤러에서는 파일을 잘 전달받았는지 간단한 테스트를 위해 MultipartFile의 사이즈를 맵에 담아 전달하도록 해 보았다.

@PostMapping("/checkFile")
@ResponseBody
public Map<String, Object> checkFile(@RequestParam(value = "file") MultipartFile file) {
    Map<String, Object> data = new HashMap<>();
    data.put("size", file.getSize());

    return data;
}

그 결과 자바스크립트 파일이 실행 되었을 떄, 아래의 텍스트를 정상적으로 로그에 찍어주는것을 확인 할 수 있었다.

image-20211229094253124

해결 끝.

반응형