我怎样才能将我的JS对象转换为FormData?

我这样做的原因是,我有一个用~100个表单字段值构造的对象。

var item = {
   description: 'Some Item',
   price : '0.00',
   srate : '0.00',
   color : 'red',
   ...
   ...
}

现在我被要求将上传文件功能添加到我的表单,当然,通过JSON是不可能的,所以我计划移动到FormData。那么有什么方法可以将我的JS对象转换为FormData呢?


当前回答

注意:这个答案并没有直接回答问题,而是给出了说明和替代方案。

人们通常使用FormData来允许他们上传文件,有三种方法可以做到这一点,我会在这个回答中详细提到它们。

1. 直接从表单中获取数据

为此,您需要在每个输入中拥有名称和值属性,然后告诉FormData从表单DOM中获取值;

let formData = new FormData(data.target as HTMLFormElement)

优点:

你不需要使用JS解决方案来获取这些值。 原生支持嵌套数据,数组等…

缺点:

您需要确保所有需要的数据都作为值属性添加到输入dom上

2. 用JS转换数据 如果你把值存储在变量中,那么你可以使用JS将它们附加到FormData中。

优点:

是否可以根据需要进行操作 你不需要在输入dom中有值属性

缺点:

自定义复杂JS附加嵌套数据到FormData对象 您需要将值存储在一个变量中

3.在单独的请求中上传文件

您可以为文件上传输入创建一个单独的表单。

优点:

您不需要等待上传提交 您不需要担心将所有数据追加到FormData对象,您只追加文件。

缺点:

在创建实体本身之前,您需要在后端处理这些上传 您需要在前端和后端处理删除文件

其他回答

也许你正在寻找这个,一个代码,接收你的javascript对象,从它创建一个FormData对象,然后POST它到你的服务器使用新的Fetch API:

    let myJsObj = {'someIndex': 'a value'};

    let datos = new FormData();
    for (let i in myJsObj){
        datos.append( i, myJsObj[i] );
    }

    fetch('your.php', {
        method: 'POST',
        body: datos
    }).then(response => response.json())
        .then(objson => {
            console.log('Success:', objson);
        })
        .catch((error) => {
            console.error('Error:', error);
        });

我有一个场景,在构造表单数据时,嵌套的JSON必须以线性方式序列化,因为这是服务器期望值的方式。所以,我写了一个小的递归函数来翻译JSON,就像这样:

{
   "orderPrice":"11",
   "cardNumber":"************1234",
   "id":"8796191359018",
   "accountHolderName":"Raj Pawan",
   "expiryMonth":"02",
   "expiryYear":"2019",
   "issueNumber":null,
   "billingAddress":{
      "city":"Wonderland",
      "code":"8796682911767",
      "firstname":"Raj Pawan",
      "lastname":"Gumdal",
      "line1":"Addr Line 1",
      "line2":null,
      "state":"US-AS",
      "region":{
         "isocode":"US-AS"
      },
      "zip":"76767-6776"
   }
}

变成这样:

{
   "orderPrice":"11",
   "cardNumber":"************1234",
   "id":"8796191359018",
   "accountHolderName":"Raj Pawan",
   "expiryMonth":"02",
   "expiryYear":"2019",
   "issueNumber":null,
   "billingAddress.city":"Wonderland",
   "billingAddress.code":"8796682911767",
   "billingAddress.firstname":"Raj Pawan",
   "billingAddress.lastname":"Gumdal",
   "billingAddress.line1":"Addr Line 1",
   "billingAddress.line2":null,
   "billingAddress.state":"US-AS",
   "billingAddress.region.isocode":"US-AS",
   "billingAddress.zip":"76767-6776"
}

服务器将接受这种转换格式的表单数据。

函数如下:

function jsonToFormData (inJSON, inTestJSON, inFormData, parentKey) {
    // http://stackoverflow.com/a/22783314/260665
    // Raj: Converts any nested JSON to formData.
    var form_data = inFormData || new FormData();
    var testJSON = inTestJSON || {};
    for ( var key in inJSON ) {
        // 1. If it is a recursion, then key has to be constructed like "parent.child" where parent JSON contains a child JSON
        // 2. Perform append data only if the value for key is not a JSON, recurse otherwise!
        var constructedKey = key;
        if (parentKey) {
            constructedKey = parentKey + "." + key;
        }

        var value = inJSON[key];
        if (value && value.constructor === {}.constructor) {
            // This is a JSON, we now need to recurse!
            jsonToFormData (value, testJSON, form_data, constructedKey);
        } else {
            form_data.append(constructedKey, inJSON[key]);
            testJSON[constructedKey] = inJSON[key];
        }
    }
    return form_data;
}

调用:

        var testJSON = {};
        var form_data = jsonToFormData (jsonForPost, testJSON);

我使用testJSON只是为了查看转换后的结果,因为我无法提取form_data的内容。AJAX post call:

        $.ajax({
            type: "POST",
            url: somePostURL,
            data: form_data,
            processData : false,
            contentType : false,
            success: function (data) {
            },
            error: function (e) {
            }
        });

你可以简单地使用:

formData.append('item', JSON.stringify(item));

使用jquery,你可以通过$.param(obj)简单地做到这一点。

例子: Const obj = { 描述:'Some Item', 价格:0.00, srate:“0.00”, 颜色:红色的 } Const form_obj = $.param(obj); . ajax({美元 url:“example.com”, 方法:“文章”, 数据:form_obj }) < script src = " https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js " > < /脚本>

其他的答案对我来说是不完整的。我从@Vladimir Novopashin的回答开始修改。以下是我需要的东西和我发现的bug:

文件支持 支持数组 Bug:复杂对象内的文件需要添加。prop而不是[prop]。例如,formData。附加('照片[0][文件]',文件)不工作在谷歌chrome,而 formData.append('照片[0]。文件',文件)工作 忽略对象中的某些属性

下面的代码应该可以在IE11和常绿浏览器上运行。

function objectToFormData(obj, rootName, ignoreList) {
    var formData = new FormData();

    function appendFormData(data, root) {
        if (!ignore(root)) {
            root = root || '';
            if (data instanceof File) {
                formData.append(root, data);
            } else if (Array.isArray(data)) {
                for (var i = 0; i < data.length; i++) {
                    appendFormData(data[i], root + '[' + i + ']');
                }
            } else if (typeof data === 'object' && data) {
                for (var key in data) {
                    if (data.hasOwnProperty(key)) {
                        if (root === '') {
                            appendFormData(data[key], key);
                        } else {
                            appendFormData(data[key], root + '.' + key);
                        }
                    }
                }
            } else {
                if (data !== null && typeof data !== 'undefined') {
                    formData.append(root, data);
                }
            }
        }
    }

    function ignore(root){
        return Array.isArray(ignoreList)
            && ignoreList.some(function(x) { return x === root; });
    }

    appendFormData(obj, rootName);

    return formData;
}