ajouter un tableau à FormData et envoyer via AJAX

j'utilise ajax pour soumettre un formulaire multipart avec tableau, champs de texte et fichiers.

j'ajoute chaque VAR aux données principales comme si

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

puis j'utilise la fonction ajax pour l'Envoyer à un fichier PHP pour stocker dans sql DB.

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

mais du côté de PHP, la variable arr , qui est un tableau apparaît comme une chaîne de caractères.

Quand Je ne l'envoie pas avec ajax comme données de forme mais utiliser le simple $.POST option Je l'obtiens comme un tableau du côté de PHP, mais alors je ne peux pas envoyer les fichiers aussi bien.

des solutions?

60
demandé sur Samuel De Backer 2013-04-19 15:56:54

5 réponses

vous avez plusieurs options:

convertissez-le en une chaîne JSON, puis analysez-le en PHP (recommandé)

JS

var json_arr = JSON.stringify(arr);

PHP

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

Ou utiliser @Curiosités de la méthode

envoie un tableau via FormData .


Non recommandé: Sérialiser les données, puis désérialiser en PHP

JS

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

PHP

$arr = explode("<#>", $_POST['arr']);
44
répondu Richard de Wit 2018-03-05 14:02:54

vous pouvez aussi envoyer un tableau via FormData de cette façon:

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

pour que vous puissiez écrire arr[] de la même manière que vous le faites avec un simple formulaire HTML. En cas de PHP, ça devrait marcher.

, Vous pouvez trouver cet article utile: Comment passer un tableau dans une chaîne de requête?

166
répondu Oleg 2017-05-23 12:02:48

C'est une vieille question mais j'ai rencontré ce problème avec l'affichage d'objets avec des fichiers récemment. J'avais besoin d'être capable de poster un objet, avec des propriétés d'enfant qui étaient des objets et des tableaux aussi bien.

la fonction ci-dessous va parcourir un objet et créer l'objet formData correct.

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

cela convertira le JSON suivant -

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

dans le FormData suivant

 name, starwars
 year, 1977
 characters[good][], luke
 characters[good][], leia
 characters[bad][], vader
5
répondu VtoCorleone 2017-03-29 18:54:45

version dactylographiée:

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

utilisant:

let formData = Utility.convertModelToFormData(model);
4
répondu Mohammad Dayyan 2018-03-20 05:25:53

version suivante valide pour les modèles contenant des arays de valeurs simples:

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
répondu Megabyte 2018-06-21 15:29:41