1、问题描述
ant design
的Upload 组件
(下称‘Upload 组件’)封装到FormData
对象后,文件对象被转换成 '[object Object]'
的字符串形式,文件流失效。
2、原因分析
先从Upload 组件
说起
Upload 组件
在文件上传前后都有诸多的回调函数,其中最常用的就是onChange
回调函数,它在上传文件状态发生改变时被调用,这个回调函数有一个参数info
,值为上传的文件对象,也正是我们需要传到后台的文件对象,如下截图:
可以清楚看到info
这个参数是一个对象,里面也包含两个对象,分别为file
和fileList
,file
是当前最近上传的一个文件对象,fileList
是一个数组,包含当前批量或多次上传的多个文件对象。
我们发现Upload 组件
把文件上传后的各种信息再次封装了一层。(不要以为这句话是废话,这里为后面埋伏笔,或者说成设铺垫。😁)
当把fileList
这个数组通过以下代码——
1 | const formData = new FormData() |
——添加到formData
对象里面后,发现formData
对象里面的fileList
字段被转换成了'[Object Object]'
,无法通过文件流的形式传到后台,这里暂且将这个对象称为一般对象
。
为什么会出现这个问题呢?下面来仔细看看FormData
对象
FormData
对象其实是在XMLHttpRequest
2级定义的,它是为序列化表以及创建与表单格式相同的数据提供便利,用于XHR传输。
再来看一看formData.append(key, values[, filename])
方法。
append()
方法会添加一个新值到FormData
对象内的一个已存在的键中,如果键不存在,则会添加该键;如果指定的键已经存在,会把新值添加到已有值集合的后面。
append()方法的参数:
name - value 中包含的数据对应的表单名称。
value - 表单的值。可以是 USVString 或 Blob (包括子类型,如 File)。
filename【可选】 - 传给服务器的文件名称 (一个 USVString), 当一个 Blob 或 File 被作为第二个参数的时候, Blob 对象的默认文件名是 “blob”。 File 对象的默认文件名是该文件的名称。
3、解决方案
通过上面value
参数的注释,我们能看到它的取值类型为USVString或者Blob
而我们刚才取值的file
或者fileList
都是javascript
的‘一般对象’,并非Blob
对象,那我们要传给后台的Blob
对象到底在哪?
通过查阅文档,发现<input type='file'>
的值(File
对象)本身就是一个Blob
对象,或者说成File
对象继承了Blob
对象。
说到这里,那我们到底该到哪里去获取File
对象呢?想必细心的你已经发现了,神秘的它就在Upload 组件
的onChange
回调函数的返回的参数中,即:
1 | onchange(info) { |
如果还不明白,请看下面的截图:
另外,Upload 组件
的官方文档中还有其他的回调函数可以拿到原生的(未经过Upload 组件
处理的)File
对象,比如beforeUpload
,详情见官方文档
总结,我们只需要简单的处理一下Upload 组件
的onChange
回调函数的返回参数,即可拿到可以封装到FormData
中的File
对象。
4、最后来一个温馨提醒
可以使用 FormData 来上传文件,但是必须得在
<form>
标签上添加属性: enctype=”multipart/form-data”如果使用 XHR 上传表单,记得设置 contentType=false,然后使用第1步的
<form>
表单。