이 글은 2년 이상 지난 이야기에요. 읽으실때 참고!
Laravel에서 ajax로 FormData 넘길때 method에 의해 발생할 수 있는 오류

그렇다.

라라벨에서는 URL Request를 여러가지 메소드를 이용해 호출할 수 있다.

넘기는 데이터가 간단히 파라미터 수준이라면 어느 메소드(put, delete, option 등)을 쓰던 문제는 없다.

 

문제

문제는 ajax로 파일을 포함한 데이터(멀티폼 데이터)와 함께 요청하는 경우인데, 보통 ajax로 파일을 넘길때는 FormData 객체를 쓰는게 간단해서 적용시켜봤더니 생각했던대로 안되는것이다.

뭔 이상한 Uncaught TypeError: Illegal invocation 에러부터 시작해서 데이터는 넘어가는데 컨트롤러에서 조회(dd($request)에 아무것도 안뜸)가 안되기도한다.

 

FormData 쓸거면 Post로 요청하자

좀 검색해보니 ajax로 FormData를 넘길때 post 방식이 아니면 뭔가 문제가 있는거같아보인다.

레퍼런스의 내용을 바탕으로 method를 별도로 명시하기도해보고 별 쌩쇼를 다해봤는데 걍 라우터를 post 허용으로 바꾸는게 더 쉽게느껴져서 그냥 ajax를 통해 멀티폼 데이터를 넘길땐 얌전히 post 방식을 쓰는게 낫다고 판단했다.

 

삽질했던 스크립트 코드

아래는 내가 사용한 ajax 요청이 이루어지는 함수의 예제이다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
function submit(id, e) {
            var tr = e.closest('tr');
            var startedAt = tr.querySelector('[name=duration_started_at]');
            if(startedAt.value === '') {
                toast('근무 시작일은 비어있을 수 없습니다.''warning');
                startedAt.focus();
 
                return false;
            }
            var endedAt = tr.querySelector('[name=duration_ended_at]');
            if(endedAt.value === '') {
                toast('근무 시작일은 비어있을 수 없습니다.''warning');
                endedAt.focus();
 
                return false;
            }
            if(Date.parse(startedAt.value) > Date.parse(endedAt.value)) {
                toast('근무 종료일은 시작일보다 이전일 수 없습니다.''warning');
                endedAt.focus();
 
                return false;
            }
            var department = tr.querySelector('[name=department]');
            if(department.value === '') {
                toast('파견과명은 비어있을 수 없습니다.''warning');
                department.focus();
 
                return false;
            }
            var remarks = tr.querySelector('[name=remarks]');
            var file = tr.querySelector('form');
            console.log(file);
 
            var formData = new FormData(file);
            formData.append('id', id);
            formData.append('duration_started_at', startedAt.value);
            formData.append('duration_ended_at', endedAt.value);
            formData.append('department', department.value);
            formData.append('remarks', remarks.value);
 
            $.ajax({
                type: 'post',
                url: '/resident/dispatch/update',
                headers: { 'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content') },
                data: formData,
                contentType: false,
                processData: false,
                success: function(data) {
                    if(id === 0) {
                        location.reload();
                    } else {
                        e.closest('tr').innerHTML = $(data).unwrap()[0].outerHTML;
                        toast('수련기록이 수정되었습니다.''success');
                    }
                },
                error: function(jqXHR) {
                    toast('수련 기록을 반영하는데 문제가 발생했습니다.''error');
                    if(APP_DEBUG) {
                        console.log(this.url);
                        popup(jqXHR.responseText);
                    }
                },
            });
        }

 

요약

1) ajax로 멀티폼 데이터를 전송하려면 FormData로 감싸서 얌전히 post 방식으로 요청보내면 된다.

2) put같은거 쓰지말자. (꼭 쓰고싶다면 레퍼런스에 방법이 있으니 도전 ㄱ)

 

D.2021-02-18 V.277