web-dev-qa-db-de.com

array an FormData anhängen und via senden AJAX

Ich verwende ajax, um ein mehrteiliges Formular mit Feldern, Textfeldern und Dateien zu übermitteln.

Ich füge jeden VAR so an die Hauptdaten an

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);

dann verwende ich die Ajax-Funktion, um es an eine PHP -Datei zu senden, um sie in SQL-DB zu speichern.

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

Auf der Seite PHP erscheint jedoch die Variable arr, bei der es sich um ein Array handelt, als Zeichenfolge.

Wenn ich es nicht mit ajax als Formulardaten sende, sondern die einfache $.POST-Option verwende, bekomme ich es als Array auf der Seite PHP, aber ich kann die Dateien auch nicht senden.

irgendwelche lösungen? 

65
shultz

Sie haben mehrere Möglichkeiten:

Konvertieren Sie es in einen JSON-String und parsen Sie es in PHP (empfohlen).

JS

var json_arr = JSON.stringify(arr);

PHP

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

Oder benutze die Methode von @ Curios

Senden eines Arrays über FormData.


Nicht empfehlenswert: Serialisieren Sie die Daten mit und deserialisieren Sie sie anschließend in PHP

JS

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

PHP

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

Sie können ein Array auch über FormData folgendermaßen senden:

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

So können Sie arr[] genauso wie mit einem einfachen HTML-Formular schreiben. Im Falle von PHP sollte es funktionieren.

Sie finden diesen Artikel möglicherweise nützlich: Wie kann ein Array in einer Abfragezeichenfolge übergeben werden?

187
Oleg

Dies ist eine alte Frage, aber ich bin vor kurzem auf das Problem gestoßen, als ich Objekte zusammen mit Dateien postete. Ich musste in der Lage sein, ein Objekt mit untergeordneten Eigenschaften zu veröffentlichen, die ebenfalls Objekte und Arrays waren. 

Die unten stehende Funktion durchläuft ein Objekt und erstellt das korrekte formData-Objekt.

// 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);
      }
    });
  }
}

Dies wird den folgenden Json konvertieren -

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

in die folgenden FormData

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

TypeScript-Version:

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;
    }
}

Mit:

let formData = Utility.convertModelToFormData(model);
4
Mohammad Dayyan

fügen Sie alle Typeneingaben zu FormData hinzu

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]) ;
}
1
HamidNE

Wenn Sie Objekte und Arrays verschachtelt haben, können Sie das FormData-Objekt am besten mit Rekursion füllen.

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);
    }
}
0
YackY

Basierend auf @YackY Antwort kürzere Rekursionsversion:

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);
    }
}

Anwendungsbeispiel:

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

Gesendete Daten:

data[a]=1&
data[b]=2&
data[c][d]=3
0
dikirill

Nächste Version gültig für Modelle, die einfache Werte enthalten:

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;
}
0
Megabyte