【CRR学习笔记】Upload上传文件+FormData相关

4,388 阅读5分钟

ES6 ANTD

背景

在做需求时,遇到点击按钮进行文件的上传,我需要处理以下几点

  1. 点击选择文件按钮跳出选择文件的小窗
  2. 限定选择文件类别为excel的两种格式
  3. 每次只能上传一个文件,文件大小低于2M
  4. 选择文件的名称呈现在按钮左侧,可以删除,再次点击选择文件按钮,新的文件替换之前的文件
  5. 点击开始上传按钮后,选择文件按钮失效,开始上传按钮文字变为上传中

……以上的等等需求。

难点

因为使用了antd封装后的Upload组件,像跳出选择框,限制文件类型,替换当前文件列表,单选等都变得很容易。 同时,点击开始上传按钮进行上传,则需要使用Upload组件中的beforeUploadcustomRequest(通过覆盖默认的上传行为,可以自定义自己的上传实现,这个在文末我会稍作阐述。)

遇到的需求是,后台请求要求为:

请求头: headers: {'content-type': 'application/form-data' }

请求参数:multipartFile: file

正常上传文件,我们可以使用form表单,FormData,jquery.form.js-表单插件来进行。这次使用FormData进行文件的上传,但是我没用过,所以进行了学习

解决过程

Upload参数配置

先看下Upload的参数列表,我只截取我用到的部分,其余参数可以自行到官网查看-Upload

Upload参数列表-1

Upload参数列表-2

Upload参数列表-3

defaultFileList 会默认显示在上传显示区,FileList 包含你已经选择的文件,所以不要再添加。 代码如下:

//支持的格式,xls,xlsx
supportType = ['application/vnd.ms-excel', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'];
//
<Upload
                  action='//这里用不到'
                  fileList={your.fileList} //呈现上传文件列表
                  accept={this.supportType} //支持的上传格式
                  onRemove={this.handleRemove} //移除文件时的调用
                  beforeUpload={this.handleBeforeUpload} // return false,用来自己操控上传
                >
                  <div className='upload-select-btn'>
                    <Button type='primary' disabled={your.chooseButtonDisabled || your.isUploading || your.isProcessing}>
                      选择文件
                    </Button>
                  </div>
                </Upload>

实际效果为:

上传文件前
上传文件后

按照官方文件列表的呈现区域为按钮下方,这里通过CSS进行了覆盖,重新调整了呈现位置和呈现区域的样式,呈现文字的大小。

BeforeUpload

如果不写BeforeUpload会默认选择完文件直接上传,所以我们需要在BeforeUpload里return false来实现手动点击按钮进行上传。 window.File实例会包含文件的修改时间,大小(size),文件名,文件的mime类型等。

//beforeUpload 附带参数当前选择的file文件,fileList文件列表
handleBeforeUpload = (file, list) => {
    const LIMIT_BYTE = 2048; // 限定2M, 1024 byte = 1 K
    if (this.supportType.includes(file.type)) { //一些限定
      if (Math.round(file.size / 1024) < LIMIT_BYTE) {
        //更新当前FileList列表,替换为新的list
      } else {
       //提示文件太大错误
      }
    } else {
       // 提醒文件格式不满足要求
    }
    return false; //一定要return false,阻止自动上传
  };

点击开始上传按钮后,我们要进行文件上传前的处理,这里就涉及了FormData的知识。

handleUpload = () => {
    const file = //你保存下来的fileList
    const formData = new FormData(); //new FormData
    formData.append('multipartFile', file[0]); //键值对形式,将一个文件添加到formData,因为每次只上传一个文件
    //更新上传中状态
    //Ajax 函数,调用你的接口函数,对接上传接口并处理返回的文件
      .then((response) => {
        //去过上传成功,更新上传状态
        //处理上传后返回的信息
      })
      .catch(() => {
      //如果上传失败,进行的相关处理
      });
  };

FormData相关知识

以前我们常通过建立form表单,进行文件的上传。

<form name='' action='接口地址' method='请求方法' enctype='multipart/form-data'>
<input type='file'>
…
</form>

表单<form>属性enctype共有二个值可选,这个属性管理的是表单的MIME编码: ①application/x-www-form-urlencoded(默认值) ②multipart/form-data form表单在你不写enctype属性时,默认值是enctype="application/x- www-form-urlencoded".

但是,在XMLHttpRequest2定义了FormData类型,它是为序列化表以及创建与表单格式相同的数据(用于XHR传输)提供便利。

先看下官方对FormData的定义:“FormData对象用以将数据编译成键值对,以便用XMLHttpRequest来发送数据。其主要用于发送表单数据,但亦可用于发送带键数据(keyed data),而独立于表单使用。

如果表单enctype属性设为multipart/form-data ,则会使用表单的submit()方法来发送数据,从而,发送数据具有同样形式”。

首先我们创建一个空FormData:

var formData = new FormData();

再调用它的方法append添加数据,例如。

formData.append('multipartFile', file,"named file.txt" )

使用append()方法时,可以通过第三个可选参数设置发送请求的头 Content-Disposition 指定文件名。如果不指定文件名(或者不支持该参数时),将使用名字“blob”。

FormData()储存数据的形式是键值对,即一对“key/value”构成一条数据,key唯一,可以对应多个value

formData还有set,get,getAll,delete,entries,has,key,values等方法。 详情见MDN-Form

现在formData有了我们上传的键值对形式的数据,再使用XHR.send(formData)将数据发送到后台接口进行文件的异步处理。

xhr.open("post",'url'); 
xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded");//设置请求头格式

如此我们就实现了文件的上传处理。

接下来,我来学习下Upload组件中的customRequst方法来覆盖默认上传行为,实现异步上传。

customRequest

官方对于该方法的参数列表如下:

customRequest参数列表

//携带那么多参数而来的customRequest
customRequest({
    action,
    data,
    file,
    filename,
    headers,
    onError,
    onProgress,
    onSuccess,
    withCredentials,
  })
customRequest = (option) => {
    const file = option.file;
    const filename = option.filename;
    var formData = new FormData();
    formData.append(filename,file);
    
    //Ajax部分-官网使用reqwest
    //processData: false
}

Over。

有疑问可以评论~~~