XieYang-blog

AntDesign的Upload组件在上传文件时,传的文件对象无效问题

1、问题描述

ant designUpload 组件(下称‘Upload 组件’)封装到FormData对象后,文件对象被转换成 '[object Object]' 的字符串形式,文件流失效。

2、原因分析

先从Upload 组件说起

Upload 组件在文件上传前后都有诸多的回调函数,其中最常用的就是onChange回调函数,它在上传文件状态发生改变时被调用,这个回调函数有一个参数info,值为上传的文件对象,也正是我们需要传到后台的文件对象,如下截图:

avatar

可以清楚看到info这个参数是一个对象,里面也包含两个对象,分别为filefileListfile是当前最近上传的一个文件对象,fileList是一个数组,包含当前批量或多次上传的多个文件对象。

我们发现Upload 组件把文件上传后的各种信息再次封装了一层。(不要以为这句话是废话,这里为后面埋伏笔,或者说成设铺垫。😁)

当把fileList这个数组通过以下代码——

1
2
const formData = new FormData()
formData.append('key', fileList)

——添加到formData对象里面后,发现formData对象里面的fileList字段被转换成了'[Object Object]',无法通过文件流的形式传到后台,这里暂且将这个对象称为一般对象

为什么会出现这个问题呢?下面来仔细看看FormData对象

FormData对象其实是在XMLHttpRequest2级定义的,它是为序列化表以及创建与表单格式相同的数据提供便利,用于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
2
3
onchange(info) {
info.file.originFileObj
}

如果还不明白,请看下面的截图:

avatar

另外,Upload 组件的官方文档中还有其他的回调函数可以拿到原生的(未经过Upload 组件处理的)File对象,比如beforeUpload,详情见官方文档

总结,我们只需要简单的处理一下Upload 组件onChange回调函数的返回参数,即可拿到可以封装到FormData中的File对象。

4、最后来一个温馨提醒

  1. 可以使用 FormData 来上传文件,但是必须得在<form>标签上添加属性: enctype=”multipart/form-data”

  2. 如果使用 XHR 上传表单,记得设置 contentType=false,然后使用第1步的<form>表单。

    更多具体详情请参考FormData文档

🐶 您的支持将鼓励我继续创作 🐶