programing

AJAX에서 중첩된 FormData 전송

elecom 2023. 8. 31. 23:38
반응형

AJAX에서 중첩된 FormData 전송

Ajax와 FormData를 사용하여 데이터를 보내야 합니다. 파일과 기타 파라미터를 보내고 싶기 때문입니다.제가 보통 데이터를 보내는 방법은 다음과 같습니다.

$.ajax({
    type:       'POST',
    url:        'some_url',
    dataType:   'json',
    processData:false,
    contentType:false,
    data:{
        Lvl_1-1: 'something',
        Lvl_1-2: 'something',
        Lvl_1-3: {
            Lvl_1-3-1: "something",
            Lvl_1-3-2: "something",
            Lvl_1-3-3: "something",
        },
    },
    ...
});

FormData()를 사용하지 않으면 문제가 없지만 FormData()를 사용하면 Lvl1의 데이터만 정상이지만 중첩된 항목은 다음과 같이 문자열로 표시됩니다.

<b>array</b> <i>(size=3)</i>
    'Lvl1-1' <font color='#888a85'>=&gt;</font> <small>string</small> 
        <font color='#cc0000'>'Something'</font> 
        <i>(length=23)</i>
    'Lvl1-2' <font color='#888a85'>=&gt;</font> <small>string</small> 
        <font color='#cc0000'>''Something''</font> <i>(length=3)</i>
    'Lvl1-3' <font color='#888a85'>=&gt;</font> <small>string</small> 
        <font color='#cc0000'>'[object Object]'</font> <i>(length=17)</i>

() 대신 내부의 데이터를 [object Object]알겠습니다[object FormData]

Lvl1-3에서 문자열 대신 배열을 얻으려면 어떻게 해야 합니까?

참고: 파일이 최상위 수준(Lvl_1)이면 FormData()를 사용하여 문제없이 파일을 보낼 수 있습니다.첨부된 파일의 코드를 작성하지 않은 것은 그것이 문제가 아니라 중첩된 데이터이기 때문입니다.FormData()를 사용하기 때문에 파일을 언급한 것입니다.

URL 인코딩 양식 데이터에는 복잡한 데이터 구조를 표현하는 기본적인 방법이 없습니다.단순 키=값 쌍만 지원합니다.

?foo=1&bar=2

대부분의 양식 데이터 구문 분석 라이브러리는 동일한 이름의 키를 사용하여 데이터 배열을 허용합니다.

?foo=1&foo=2

PHP는 그 형식 위에 자체 구문을 볼트로 고정했습니다.

?foo[]=1&foo[]=2

연관 배열에서 명명된 키를 허용했습니다.

?foo[bar]=1&foo[baz]=2

및 중첩 배열:

?foo[bar][level2a]=1&foo[bar][level2b]=2

PHP의를 PHP로 때폼하기 위한 했습니다.data.

당신이 경우용을 사용하고 .FormData그러면 jQuery가 재처리하지 않습니다.

있는 의 그 않았습니다를 두 번째 입니다.append여기서 문자열이 필요합니다.

직접 PHP의 구문을 사용하여 키 이름을 생성해야 합니다.

form_data_instance.append("Lvl_1-3[Lvl_1-3-1]", "something");
form_data_instance.append("Lvl_1-3[Lvl_1-3-2]", "something");
form_data_instance.append("Lvl_1-3[Lvl_1-3-3]", "something");

저는 중첩된 매개 변수를 문자열화하고 다른 쪽에서 구문 분석합니다.

예를 들어, 제가 합격하고 싶다면:

{"sthing":
  {"sthing":"sthing"},
  {"picture":
    {"legend":"great legend"},
    {"file":"great_picture.jpg"}
  }
}

그럼, 나는...

// On the client side
const nestedParams = {"sthing":
                       {"sthing":"sthing"},
                       {"picture":
                         {"legend":"great legend"}
                       }
                     };
const pictureFile = document.querySelector('input[type="file"]')[0];
const formDataInstance = new FormData;
formDataInstance.append("nested_params": JSON.stringify(nested_params);
formDataInstance.append("file": document.querySelector('input[type="file"]')[0]);


// On the server side
params["nested_params"] = JSON.parse(params["nested_params"]);
params["nested_params"]["sthing"]["picture"]["file"] = params["file"];

Quentin의 답변에 덧붙여, 저는 다음과 같은 PHP Laravel 코드를 가지고 있었습니다.

    $tags = [];
    foreach ($request->input('tags') as $tag) {
        if (!is_array($tag)) {
            $new_tag = Tag::generate($tag);
            array_push($tags, $new_tag->id);
        } else {
            array_push($tags, $tag['id']);
        }
    }

배열로 해서 빈 로 배 시 하 작 값 볼 수 있 습 니 다 것 채 는 을 우 로 으 열 다 여 음 , ▁from 니 다 있 습 ▁you ▁it 수 ▁values ▁array ▁empty ▁with 볼 ▁see 빈 ▁an ▁i ▁fill ▁and ▁can ▁with ▁then ▁i ▁start열 배$request->input('tags')해당 요청 입력은 다차원 배열이므로 이 질문에 설명된 문제가 발생했습니다.FormData를 사용할 때만 나타납니다.multipart/form-data양식 인코딩 형식입니다.

저는 Quentin의 답변과 여기에 있는 클라이언트 측 JavaScript 코드로 이 문제를 해결할 수 있었습니다.

this.example.tags.forEach((tag, i) => {
    if (Object.prototype.toString.call(tag) === '[object String]') {
        payload.append(`tags[${i}]`, tag);
    } else {
        Object.keys(tag).forEach(field => payload.append(`tags[${i}][${field}]`, tag[field]));
    }
});

이 코드는 먼저 FormData에 추가하려는 태그가 문자열인지 확인합니다.그렇다면 존재하지 않는 새 태그입니다.그런 다음 인덱스 번호로 추가합니다.태그가 이미 존재한다면, 나는 고객이 가지고 있던 모든 값을 보냅니다.의 경우,ID(행 에 대한 관계)만, " " " " " " " " " 와 같은 입니다. 그러나 다음과 같은 구문을 사용하는 데는 좋은 연습이 됩니다.arr[index][field].

쿠엔틴과 내 대답을 공부하면 패턴을 볼 수 있을 것입니다.저의 사례 또한 본질적으로 다소 사소하지 않은 점이 있으므로 제 의견으로 검토해 보면 좋을 것입니다.

완전히 이해하기 위해 페이로드는 다음과 같습니다.

  'tags' => 
  array (
    0 => 
    array (
      'id' => '2',
      'name' => 'React JS',
    ),
    1 => 
    array (
      'id' => '5',
      'name' => 'JSON Web Tokens',
    ),
    2 => 'Sandwiches',
  ),

3개의 태그가 있는 것을 볼 수 있습니다.처음 두 개는 이미 존재합니다.세 번째 것은 내 데이터베이스에 존재하지 않기 때문에 객체가 아닌 문자열 값으로 들어옵니다.Laravel/PHP는 중첩된 개체 "기존 태그"를 좋아하지 않기 때문에 FormData(이미지가 있는 다중 부분 인코딩 유형)를 수정해야 했습니다.

다음은 전체 submitForm 함수입니다.

const payload = new FormData();

Object.keys(this.example).forEach(field => payload.append(field, this.example[field]));

this.example.tags.forEach((tag, i) => {
    if (Object.prototype.toString.call(tag) === '[object String]') {
        payload.append(`tags[${i}]`, tag);
    } else {
        Object.keys(tag).forEach(field => payload.append(`tags[${i}][${field}]`, tag[field]));
    }
});

this.example.images.forEach(image => payload.append('images[]', image));

const response = await axios.post(route('admin.examples.create'), payload);

참조:JavaScript에서 변수가 문자열인지 확인합니다.

언급URL : https://stackoverflow.com/questions/28774746/sending-nested-formdata-on-ajax

반응형