Добавление массива в FormData и отправка через AJAX
Я использую ajax для отправки многостраничной формы с массивом, текстовыми полями и файлами.
Я добавляю каждый VAR к основным данным так
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);
то я использую функцию ajax для отправки ее в файл PHP для хранения внутри SQL-DB.
$.ajax({
type: "post",
url: 'php/submittionform.php',
cache: false,
processData: false,
contentType: false,
data: data,
success: function(request) {$('#box').html(request); }
})
Но на стороне PHP переменная arr
, представляющая собой массив, появляется как строка.
Когда я не отправляю его с помощью ajax в качестве данных формы, но использую простой параметр $.POST
, я получаю его как массив на стороне PHP, но затем я не могу отправить файлы также.
любые решения?
Ответы
Ответ 1
У вас есть несколько вариантов:
Преобразуйте его в строку JSON, а затем проанализируйте в PHP (рекомендуется)
JS
var json_arr = JSON.stringify(arr);
PHP
$arr = json_decode($_POST['arr']);
Отправка массива через FormData
.
Не рекомендуется: сериализировать данные с помощью, а затем десериализовать в PHP
JS
// Use <#> or any other delimiter you want
var serial_arr = arr.join("<#>");
PHP
$arr = explode("<#>", $_POST['arr']);
Ответ 2
Вы также можете отправить массив через FormData
следующим образом:
var formData = new FormData;
var arr = ['this', 'is', 'an', 'array'];
for (var i = 0; i < arr.length; i++) {
formData.append('arr[]', arr[i]);
}
Итак, вы можете написать arr[]
так же, как вы это делаете, с простой формой HTML. В случае PHP он должен работать.
Вы можете найти эту статью полезной: Как передать массив в строке запроса?
Ответ 3
Это старый вопрос, но я столкнулся с этой проблемой при публикации объектов вместе с файлами в последнее время. Мне нужно было разместить объект с дочерними свойствами, которые также были объектами и массивами.
Функция ниже будет проходить через объект и создать правильный объект formData.
// 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);
}
});
}
}
Это преобразует следующий json -
{
name: 'starwars',
year: 1977,
characters: {
good: ['luke', 'leia'],
bad: ['vader'],
},
}
в следующий FormDatap >
name, starwars
year, 1977
characters[good][], luke
characters[good][], leia
characters[bad][], vader
Ответ 4
Версия машинописного текста:
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;
}
}
С помощью:
let formData = Utility.convertModelToFormData(model);
Ответ 5
добавить все типы ввода в FormData
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]) ;
}
Ответ 6
Если у вас есть вложенные объекты и массивы, лучший способ заполнить объект FormData - использовать рекурсию.
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);
}
}
Ответ 7
Следующая версия действительна для модели, содержащей массивы простых значений:
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;
}
Ответ 8
Это работает для меня, когда я отправил файл + текст + массив:
const uploadData = new FormData();
if (isArray(value)) {
const k = '${key}[]';
uploadData.append(k, value);
} else {
uploadData.append(key, value);
}
const headers = {
'Content-Type': 'multipart/form-data',
};
Ответ 9
Исходя из @YackY, ответьте более короткой рекурсивной версией:
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);
}
}
Пример использования:
var data = {a: '1', b: 2, c: {d: '3'}};
var formData = new FormData();
createFormData(formData, 'data', data);
Отправленные данные:
data[a]=1&
data[b]=2&
data[c][d]=3