使用FormData.append()传文件至后端,Firefox/Safari报参数非对象错误
跨浏览器FormData上传问题排查与解决
看起来你遇到的是Chrome与Firefox/Safari在FormData参数处理上的兼容性差异——Chrome对非标准参数有容错机制,但Firefox和Safari严格遵循W3C规范,所以会抛出Argument 2 of FormData.append is not an object错误。
问题根源
FormData的append()方法标准要求第二个参数只能是以下类型之一:
USVString(字符串)Blob(包括子类File)
Chrome会自动将非上述类型的参数(比如普通JavaScript对象)转换为字符串(比如[object Object]),但Firefox和Safari会直接校验参数类型,发现是不允许的对象时就抛出错误。
从你的代码片段看,问题出在childData.forEach((data: any) => ...)这部分——你大概率是直接把childData里的整个对象(包含文件和文档详情)传给了formData.append(),而不是拆解成合法的参数类型。
解决方案
根据你的业务需求,有两种常见的修复方式:
1. 拆分字段单独上传(推荐,适用于包含File的场景)
如果childData的每个项是包含File和其他文档字段的对象,需要把File和普通字段分别append到FormData:
childData.forEach((item: any, index: number) => { // 上传文件:确保item.file是File/Blob类型 if (item.file && item.file instanceof File) { formData.append(`childFiles[${index}]`, item.file, item.file.name); } // 上传文档详情:逐个append字符串类型的字段 formData.append(`childDocs[${index}][title]`, item.title || ''); formData.append(`childDocs[${index}][description]`, item.description || ''); // 其他字段依此类推... });
2. 将非文件数据序列化为JSON上传
如果你的文档详情是复杂嵌套对象,不想逐个拆解,可以把非File部分转成JSON字符串再上传,后端再解析:
childData.forEach((item: any, index: number) => { // 单独上传File if (item.file && item.file instanceof File) { formData.append(`childFiles[${index}]`, item.file, item.file.name); } // 把非File的文档详情转成JSON字符串 const docDetails = { ...item }; delete docDetails.file; // 移除File字段,因为无法被JSON序列化 formData.append(`childDocs[${index}]`, JSON.stringify(docDetails)); });
额外注意事项
- 确保所有传给
append()的第二个参数都是合法类型:避免直接传入undefined、null或者普通对象。 - 如果
childData里有数组类型的字段,同样需要拆解或者转成字符串后再上传。 - 可以在append前加类型校验,提前规避错误:
const isValidFormValue = (val: any) => { return typeof val === 'string' || val instanceof Blob; };
内容的提问来源于stack exchange,提问作者Arun Kumar
相关产品推荐
相关产品推荐

