FormData'ya dizi eklemek ve AJAX aracılığıyla göndermek


109

Dizi, metin alanları ve dosyalar içeren çok parçalı bir form göndermek için ajax kullanıyorum.

Her bir VAR'ı ana verilere ekliyorum

var attachments = document.getElementById('files'); 
var data= new FormData();

for (i=0; i< attachments.files.length; i++){
    data.append('file', attachments.files[i]);
    console.log(attachments.files[i]);

    data.append ('headline', headline);
    data.append ('article', article);
    data.append ('arr', arr);
    data.append ('tag', tag);

daha sonra ajax işlevini sql DB içinde saklamak üzere bir PHP dosyasına göndermek için kullanıyorum.

$.ajax({    
    type: "post",
    url: 'php/submittionform.php',
    cache: false,
    processData: false,
    contentType: false,
    data: data,
    success: function(request) {$('#box').html(request); }
})

Ancak PHP tarafında, arrbir dizi olan değişken bir dizge olarak görünür.

Form verisi olarak ajax ile göndermediğimde, ancak basit $.POSTseçeneği kullandığımda, onu PHP tarafında bir dizi olarak alıyorum, ancak o zaman dosyaları da gönderemiyorum.

herhangi bir çözüm?

Yanıtlar:


93

Birkaç seçeneğiniz var:

Bir JSON dizesine dönüştürün, ardından PHP'de ayrıştırın (önerilir)

JS

var json_arr = JSON.stringify(arr);

PHP

$arr = json_decode($_POST['arr']);

Veya @ Curios'un yöntemini kullanın

Bir dizi üzerinden gönderme FormData.


Önerilmez: Verileri ile serileştirin, ardından PHP'de seriyi kaldırın

JS

// Use <#> or any other delimiter you want
var serial_arr = arr.join("<#>"); 

PHP

$arr = explode("<#>", $_POST['arr']);

1
sorun, dizinin boşluklar ve noktalama işaretleriyle birlikte GERÇEK metin satırları içermesidir. Bunu mahvetmek istemiyorum.
shultz

3
JSON ile kodladığınızda ve ayrıştırdığınızda veriler kaybolmaz. Deneyin;)
Richard de Wit

Asp.net'i otomatik haritalama veya benzeri bir şeyle kullanıyorsanız, ihtiyacınız olan şey @ Meraklı cevaptır.
Martín Coll

1
@Richard de Wit Dosya veya Form Verileri gibi verileriniz varsa, bunları json.stringfy'da kaybedersiniz
Mohsen

Daha çok, daha basit halatı severim. [] Kullanarak dizi dizilerini geçirmek için bir çeşit özyineleme yapmanız gerektiğinden, bunun bu şekilde yapılabileceğini bilmek güzel.
Chopnut

260

FormDataBu yolla da bir dizi gönderebilirsiniz :

var formData = new FormData;
var arr = ['this', 'is', 'an', 'array'];
for (var i = 0; i < arr.length; i++) {
    formData.append('arr[]', arr[i]);
}

Böylece arr[]basit bir HTML formu ile yaptığınız gibi yazabilirsiniz . PHP durumunda çalışmalıdır.

Bu makaleyi yararlı bulabilirsiniz: Bir sorgu dizesi içinde bir dizi nasıl geçirilir?


1
@Oleg yazmaya gerek nedir arr[]içinde formData.append('arr[]', arr[i]);? neden değil arrdüzeltmek? İkisini de denedim ama sadece arr[]çalıştım.
Totoro

@Totoro, çünkü arrher döngü yinelemesinde bu değeri yeniden tanımlamanız durumunda ve sonunda, son değer son dizi öğesine eşit olur, ancak tüm diziye eşit olmaz
Oleg

@Oleg Durum yeniden tanımlamaksa, o zaman içinde farklı olan nedir arr[], neden arr[]yeniden tanımlanmadı? arr[]aynı zamanda bir dizedir. Ve hem test ederken ne arrde arr[]benim durumumda yeniden tanımlandı. FormData'da aynı anahtara ancak farklı değere sahip birden çok dizi aldım. Yani ben var arrdeğerle 1ve başka arrdeğerle 2.
Totoro

@Totoro evet, haklısın, benim hatam. Bunun daha çok sunucu tarafına özgü bir soru olduğuna inanıyorum. Farklı diller, sorgu dizesini farklı şekilde ayrıştırabilir. Örneğin, PHP tanımladığınız gibi davranıyor, ancak örnekler gördüm (bellek hizmet veriyorsa, Java'da), burada arrdiziler için de çalıştı. Gelen bu konu bu sorunun daha ayrıntılı bir cevap var
Oleg

Bir nesne dizisi göndermek isteyen varsa, bu yanıtı şu şekilde uzatabilirsinizfor (var i = 0; i < myArr; i++) { var myItemInArr = myArr[i]; for (var prop in myItemInArr) { fileData.append(`myArr[${i}][${prop}]`, myItemInArr[prop]); } }
edqwerty

7

Bu eski bir soru, ancak son zamanlarda dosyalarla birlikte nesneler gönderirken bu sorunla karşılaştım. Nesneler ve diziler olan alt özelliklere sahip bir nesneyi gönderebilmem gerekiyordu.

Aşağıdaki işlev bir nesnenin içinden geçecek ve doğru formData nesnesini oluşturacaktır.

// formData - instance of FormData object
// data - object to post
function getFormData(formData, data, previousKey) {
  if (data instanceof Object) {
    Object.keys(data).forEach(key => {
      const value = data[key];
      if (value instanceof Object && !Array.isArray(value)) {
        return this.getFormData(formData, value, key);
      }
      if (previousKey) {
        key = `${previousKey}[${key}]`;
      }
      if (Array.isArray(value)) {
        value.forEach(val => {
          formData.append(`${key}[]`, val);
        });
      } else {
        formData.append(key, value);
      }
    });
  }
}

Bu, aşağıdaki json'u dönüştürecektir -

{
  name: 'starwars',
  year: 1977,
  characters: {
    good: ['luke', 'leia'],
    bad: ['vader'],
  },
}

aşağıdaki FormData'ya

 name, starwars
 year, 1977
 characters[good][], luke
 characters[good][], leia
 characters[bad][], vader

Benim için faydalı oldu, sadece ekleme içindeki değere String (değer) uygulamak zorundaydı (aksi takdirde doğru / yanlış için başarısız olur). Ayrıca boş değerlerde başarısız olmak (value !== null) && formData.append(key, value)yerine de olmalıformData.append(key, value)
Alexander

7

Typescript sürümü:

export class Utility {      
    public static convertModelToFormData(model: any, form: FormData = null, namespace = ''): FormData {
        let formData = form || new FormData();
        let formKey;

        for (let propertyName in model) {
            if (!model.hasOwnProperty(propertyName) || !model[propertyName]) continue;
            let formKey = namespace ? `${namespace}[${propertyName}]` : propertyName;
            if (model[propertyName] instanceof Date)
                formData.append(formKey, model[propertyName].toISOString());
            else if (model[propertyName] instanceof Array) {
                model[propertyName].forEach((element, index) => {
                    const tempFormKey = `${formKey}[${index}]`;
                    this.convertModelToFormData(element, formData, tempFormKey);
                });
            }
            else if (typeof model[propertyName] === 'object' && !(model[propertyName] instanceof File))
                this.convertModelToFormData(model[propertyName], formData, formKey);
            else
                formData.append(formKey, model[propertyName].toString());
        }
        return formData;
    }
}

Kullanımı:

let formData = Utility.convertModelToFormData(model);

harika iş, süper kullanışlı: D
Cosimo Chellini

3

tüm tür girişlerini FormData'ya ekle

const formData = new FormData();
for (let key in form) {
    Array.isArray(form[key])
        ? form[key].forEach(value => formData.append(key + '[]', value))
        : formData.append(key, form[key]) ;
}

2

Yuvalanmış nesneleriniz ve dizileriniz varsa, FormData nesnesini doldurmanın en iyi yolu özyinelemeyi kullanmaktır.

function createFormData(formData, data, key) {
    if ( ( typeof data === 'object' && data !== null ) || Array.isArray(data) ) {
        for ( let i in data ) {
            if ( ( typeof data[i] === 'object' && data[i] !== null ) || Array.isArray(data[i]) ) {
                createFormData(formData, data[i], key + '[' + i + ']');
            } else {
                formData.append(key + '[' + i + ']', data[i]);
            }
        }
    } else {
        formData.append(key, data);
    }
}

1

Sonraki sürüm, basit değerler içeren model için geçerlidir:

function convertModelToFormData(val, formData = new FormData(), namespace = '') {
    if((typeof val !== 'undefined') && (val !== null)) {
        if(val instanceof Date) {
            formData.append(namespace, val.toISOString());
        } else if(val instanceof Array) {
            for(let element of val) {
                convertModelToFormData(element, formData, namespace + '[]');
            }
        } else if(typeof val === 'object' && !(val instanceof File)) {
            for (let propertyName in val) {
                if(val.hasOwnProperty(propertyName)) {
                    convertModelToFormData(val[propertyName], formData, namespace ? namespace + '[' + propertyName + ']' : propertyName);
                }
            }
        } else {
            formData.append(namespace, val.toString());
        }
    }
    return formData;
}

1

@YackY cevabının kısa özyineleme versiyonuna göre:

function createFormData(formData, key, data) {
    if (data === Object(data) || Array.isArray(data)) {
        for (var i in data) {
            createFormData(formData, key + '[' + i + ']', data[i]);
        }
    } else {
        formData.append(key, data);
    }
}

Kullanım örneği:

var data = {a: '1', b: 2, c: {d: '3'}};
var formData = new FormData();
createFormData(formData, 'data', data);

Gönderilen veriler:

data[a]=1&
data[b]=2&
data[c][d]=3
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.