nối mảng vào FormData và gửi qua AJAX


109

Tôi đang sử dụng ajax để gửi biểu mẫu nhiều phần với mảng, trường văn bản và tệp.

Tôi nối mỗi VAR vào dữ liệu chính như vậy

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

sau đó tôi sử dụng hàm ajax để gửi nó đến một tệp PHP để lưu trữ bên trong sql DB.

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

Nhưng về phía PHP, arrbiến, là một mảng xuất hiện dưới dạng một chuỗi.

Khi tôi không gửi nó với ajax dưới dạng dữ liệu Biểu mẫu mà sử dụng $.POSTtùy chọn đơn giản, tôi nhận nó dưới dạng một mảng ở phía PHP, nhưng sau đó tôi cũng không thể gửi tệp.

bất kỳ giải pháp?

Câu trả lời:


93

Bạn có một số tùy chọn:

Chuyển đổi nó thành một chuỗi JSON, sau đó phân tích cú pháp nó bằng PHP (được khuyến nghị)

JS

var json_arr = JSON.stringify(arr);

PHP

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

Hoặc sử dụng phương pháp của @ Curios

Gửi một mảng qua FormData.


Không được khuyến nghị: Tuần tự hóa dữ liệu với, sau đó giải mã hóa bằng PHP

JS

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

PHP

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

1
vấn đề là mảng chứa các dòng văn bản THỰC, với khoảng trắng và dấu chấm câu. Tôi không muốn làm nó rối tung lên.
shultz

3
Khi bạn mã hóa và phân tích cú pháp nó bằng JSON, dữ liệu sẽ không bị mất. Hãy thử;)
Richard de Wit

Nếu bạn đang sử dụng asp.net với ánh xạ tự động hoặc thứ gì đó tương tự, thì câu trả lời @Curious chính là thứ bạn cần.
Martín Coll

1
@Richard de Wit Nếu bạn có dữ liệu File hoặc FormData như vậy, bạn sẽ mất chúng trong json.stringfy
Mohsen

Tôi thích xâu chuỗi tốt hơn, đơn giản hơn. Vì bạn cần thực hiện một số loại đệ quy để chuyển mảng mảng bằng cách sử dụng [] nhưng bạn nên biết rằng có thể thực hiện theo cách đó.
Chopnut

260

Bạn cũng có thể gửi một mảng qua FormDatacách này:

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

Vì vậy, bạn có thể viết arr[]giống như cách bạn làm với một biểu mẫu HTML đơn giản. Trong trường hợp của PHP, nó sẽ hoạt động.

Bạn có thể thấy bài viết này hữu ích: Làm thế nào để truyền một mảng trong một chuỗi truy vấn?


1
@Oleg cần phải viết là gì arr[]trong formData.append('arr[]', arr[i]);? tại sao không arrđúng? Tôi đã thử cả hai nhưng chỉ arr[]hiệu quả.
Totoro

@Totoro vì trong trường hợp arrcủa bạn chỉ cần xác định lại giá trị này trên mỗi lần lặp, và cuối cùng, giá trị cuối cùng sẽ bằng với phần tử mảng cuối cùng, nhưng không phải là toàn bộ mảng
Oleg

@Oleg Nếu trường hợp xác định lại là trường hợp thì có gì khác biệt ở chỗ arr[], tại sao không arr[]xác định lại? arr[]cũng là một chuỗi. Và trong khi thử nghiệm cả hai arrcũng không arr[]được xác định lại trong trường hợp của tôi. Tôi nhận được nhiều mảng trong FormData với cùng một khóa nhưng giá trị khác nhau. Vì vậy, tôi nhận được arrvới giá trị 1và một arrgiá trị khác 2.
Totoro

@Totoro vâng, bạn nói đúng, lỗi của tôi. Tôi tin rằng đây là câu hỏi dành riêng cho từng máy chủ. Các ngôn ngữ khác nhau có thể phân tích cú pháp chuỗi truy vấn khác nhau. Ví dụ: PHP hoạt động giống như bạn đã mô tả, nhưng tôi đã thấy các ví dụ (nếu bộ nhớ phục vụ, trong Java), nơi arrcũng hoạt động cho các mảng. Trong chủ đề này có một câu trả lời chi tiết hơn cho câu hỏi này
Oleg

Nếu bất cứ ai đang tìm cách gửi một mảng của các đối tượng, bạn có thể mở rộng câu trả lời này như saufor (var i = 0; i < myArr; i++) { var myItemInArr = myArr[i]; for (var prop in myItemInArr) { fileData.append(`myArr[${i}][${prop}]`, myItemInArr[prop]); } }
edqwerty

7

Đây là một câu hỏi cũ nhưng tôi đã gặp phải vấn đề này với việc đăng các đối tượng cùng với tệp gần đây. Tôi cần có thể đăng một đối tượng, với các thuộc tính con là các đối tượng và mảng.

Hàm bên dưới sẽ đi qua một đối tượng và tạo đối tượng formData chính xác.

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

Điều này sẽ chuyển đổi json sau:

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

vào FormData sau

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

Nó rất hữu ích đối với tôi, chỉ cần áp dụng String (value) trên giá trị bên trong append (nếu không thì nó không thành công với true / false). Ngoài ra nó nên (value !== null) && formData.append(key, value)thay vì chỉ formData.append(key, value)nếu không nó không thành công trên các giá trị null
Alexander

7

Phiên bản sắp xếp:

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

Sử dụng:

let formData = Utility.convertModelToFormData(model);

công việc tuyệt vời, siêu hữu ích: D
Cosimo Chellini

3

thêm tất cả các đầu vào kiểu vào 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]) ;
}

2

Nếu bạn có các đối tượng và mảng lồng nhau, cách tốt nhất để điền đối tượng FormData là sử dụng đệ quy.

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

Phiên bản tiếp theo hợp lệ cho mô hình có chứa các giá trị đơn giản:

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

Dựa trên câu trả lời @YackY phiên bản đệ quy ngắn hơn:

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

Ví dụ sử dụng:

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

Dữ liệu đã gửi:

data[a]=1&
data[b]=2&
data[c][d]=3
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.