我怎样才能将我的JS对象转换为FormData?
我这样做的原因是,我有一个用~100个表单字段值构造的对象。
var item = {
description: 'Some Item',
price : '0.00',
srate : '0.00',
color : 'red',
...
...
}
现在我被要求将上传文件功能添加到我的表单,当然,通过JSON是不可能的,所以我计划移动到FormData。那么有什么方法可以将我的JS对象转换为FormData呢?
下面是一个使用Object.entries()的简单而甜蜜的解决方案,它甚至可以处理嵌套对象。
// If this is the object you want to convert to FormData...
const item = {
description: 'First item',
price: 13,
photo: File
};
const formData = new FormData();
Object.entries(item).forEach(([key, value]) => {
formData.append(key, value);
});
// At this point, you can then pass formData to your handler method
阅读更多关于Object.entries()在这里- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/entries
在我的例子中,我的对象也有属性,即文件数组。因为它们是二进制的,所以应该以不同的方式处理——索引不需要是键的一部分。所以我修改了@Vladimir Novopashin和@developer033的答案:
export function convertToFormData(data, formData, parentKey) {
if(data === null || data === undefined) return null;
formData = formData || new FormData();
if (typeof data === 'object' && !(data instanceof Date) && !(data instanceof File)) {
Object.keys(data).forEach(key =>
convertToFormData(data[key], formData, (!parentKey ? key : (data[key] instanceof File ? parentKey : `${parentKey}[${key}]`)))
);
} else {
formData.append(parentKey, data);
}
return formData;
}
其他的答案对我来说是不完整的。我从@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;
}
注意:这个答案并没有直接回答问题,而是给出了说明和替代方案。
人们通常使用FormData来允许他们上传文件,有三种方法可以做到这一点,我会在这个回答中详细提到它们。
1. 直接从表单中获取数据
为此,您需要在每个输入中拥有名称和值属性,然后告诉FormData从表单DOM中获取值;
let formData = new FormData(data.target as HTMLFormElement)
优点:
你不需要使用JS解决方案来获取这些值。
原生支持嵌套数据,数组等…
缺点:
您需要确保所有需要的数据都作为值属性添加到输入dom上
2. 用JS转换数据
如果你把值存储在变量中,那么你可以使用JS将它们附加到FormData中。
优点:
是否可以根据需要进行操作
你不需要在输入dom中有值属性
缺点:
自定义复杂JS附加嵌套数据到FormData对象
您需要将值存储在一个变量中
3.在单独的请求中上传文件
您可以为文件上传输入创建一个单独的表单。
优点:
您不需要等待上传提交
您不需要担心将所有数据追加到FormData对象,您只追加文件。
缺点:
在创建实体本身之前,您需要在后端处理这些上传
您需要在前端和后端处理删除文件