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

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

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

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


当前回答

这个方法将一个JS对象转换为一个FormData:

function convertToFormData(params) { return Object.entries(params) .reduce((acc, [key, value]) => { if (Array.isArray(value)) { value.forEach((v, k) => acc.append(`${key}[${k}]`, value)); } else if (typeof value === 'object' && !(value instanceof File) && !(value instanceof Date)) { Object.entries(value).forEach((v, k) => acc.append(`${key}[${k}]`, value)); } else { acc.append(key, value); } return acc; }, new FormData()); }

其他回答

我使用这个Post我的对象数据作为表单数据。

const encodeData = require('querystring');

const object = {type: 'Authorization', username: 'test', password: '123456'};

console.log(object);
console.log(encodeData.stringify(object));

递归地

const toFormData = (f => f(f))(h => f => f(x => h(h)(f)(x)))(f => fd => pk => d => { if (d instanceof Object) { Object.keys(d).forEach(k => { const v = d[k] if (pk) k = `${pk}[${k}]` if (v instanceof Object && !(v instanceof Date) && !(v instanceof File)) { return f(fd)(k)(v) } else { fd.append(k, v) } }) } return fd })(new FormData())() let data = { name: 'John', age: 30, colors: ['red', 'green', 'blue'], children: [ { name: 'Max', age: 3 }, { name: 'Madonna', age: 10 } ] } console.log('data', data) document.getElementById("data").insertAdjacentHTML('beforeend', JSON.stringify(data)) let formData = toFormData(data) for (let key of formData.keys()) { console.log(key, formData.getAll(key).join(',')) document.getElementById("item").insertAdjacentHTML('beforeend', `<li>${key} = ${formData.getAll(key).join(',')}</li>`) } <p id="data"></p> <ul id="item"></ul>

2022年更新

Axios现在支持将对象自动序列化为FormData

从0.27版开始,如果请求的Content-Type报头被设置为multipart/form-data, Axios就支持将对象自动序列化为FormData对象。阅读更多

嵌套对象和文件

下面的解决方案处理嵌套对象、数组和文件。

const buildFormData = (formData: FormData, data: FormVal, parentKey?: string) => {
    if (Array.isArray(data)) {
        data.forEach((el) => {
            buildFormData(formData, el, parentKey)
        })

    } else if (typeof data === "object" && !(data instanceof File)) {
        Object.keys(data).forEach((key) => {
            buildFormData(formData, (data as FormDataNest)[key], parentKey ? `${parentKey}.${key}` : key)
        })

    } else {
        if (isNil(data)) {
            return
        }

        let value = typeof data === "boolean" || typeof data === "number" ? data.toString() : data
        formData.append(parentKey as string, value)
    }
}

export const getFormData = (data: Record<string, FormDataNest>) => {
    const formData = new FormData()

    buildFormData(formData, data)

    return formData
}

类型

type FormDataPrimitive = string | Blob | number | boolean

interface FormDataNest {
  [x: string]: FormVal
}

type FormVal = FormDataNest | FormDataPrimitive

尝试 obj2fd=> https://www.npmjs.com/package/obj2fd

import obj2fd from 'obj2fd'

let data = {a:1, b:2, c:{ca:1}};
let dataWithFormData = obj2fd(data);
//result => [a=>1, b=>2, c=>[ca=>1]]

其他的答案对我来说是不完整的。我从@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;
}