antd 和 element上传文件详解与FormData详解

背景

平时工做中常常会遇到须要上传文件的状况,若是你用ant design 或者element ,它们都提供了上传的组件。 咱们分别来看一下element 和 antd 手动上传怎么处理:javascript

ant design 手动上传文件

antd官网有手动上传的demo:
在这里简单写一写实现,主要有 在jsx中引入Upload组件,将 fileList 做为props传入,fileList为选择的文件列表,和 上传函数的实现。php

// jsx
 <div>
    <Upload fileList={this.state.fileList}>     // Upload 为上传组件
      <Button>
        <Icon type="upload" /> Select File
      </Button>
    </Upload>
    <Button onClick={this.handleUpload}>
        上传文件
    </Button>
</div>
//  handleUpload 的实现 使用 fetch 请求
const handleUpload = () {
    const formData = new FormData();
    fileList.forEach((file) => {   // fileList 是要上传的文件数组
      formData.append('files[]', file);
    });
    
    fetch(url: 'http:just.a.url.demo', {
      method: 'POST',
      headers: {
            credentials: 'same-origin'
          // 'Content-Type': 'multipart/form-data'  // 不要加上这个文件类型说明
      },
      body: formData
            
    })
    .then(response => response.json())
    .catch(error => console.error('Error:', error))
    .then(response => console.log('Success:', response));
}

Element 手动上传文件

element 和antd 不一样,经过上传组件拿回的数据,element又封装了一层,因此传数据稍有不一样。
如下是简单实现:html

// template
<el-upload 
    :file-list="fileList"
    :auto-upload="false">
    <el-button slot="trigger" type="primary">选择文件</el-button>
    <el-button @click="submitUpload">上传文件</el-button>
</el-upload>
//  上传实现

const handleUpload = () {
    const formData = new FormData();
    fileList.forEach((file) => {        
        formData.append('files[]', file.raw);  // 这里与antd 不一样的是,文件真正数据为 file.raw 
    });
    
    fetch(url: 'http:just.a.url.demo', {
      method: 'POST',
      headers: {
            credentials: 'same-origin'
          // 'Content-Type': 'multipart/form-data'  // 不要加上这个文件类型说明
      },
      body: formData
            
    })
    .then(response => response.json())
    .catch(error => console.error('Error:', error))
    .then(response => console.log('Success:', response));
}

想问几个问题:

虽然能够找得demo把文件传输了出去,可是内心有几个问题,以下:java

1. 问什么传文件须要用FormData格式呢?传文件和传通常数据有什么不同?

从传文件的历史来回答传文件问什么须要FormData 格式。ajax

  • file 形式

在最开始的时候,文件上传的传统形式是使用 表单元素file。参照下面的代码:chrome

  <form id="upload-form" action="upload.php" method="post" enctype="multipart/form-data" >

    <input type="file" id="upload" name="upload" /> <br />

    <input type="submit" value="Upload" />

  </form>

它在chrome浏览器中是这个样子:
json

选择文件以后,点击Upload 按钮,文件开始上传。api

  • iframe形式

使用form元素比较简单,但缺点也比较明显:上传同步、上传完成页面会刷新;
在HTML5出现以前,想要实现文件异步上传,只能经过iframe+form实现;
其原理是:文件上传时在页面中动态建立一个iframe元素和一个form元素,并将form元素的target属性指向动态建立iframe元素。当用户完成选择文件动做时,提交子页面中的 form。这时,iframe跳转,而父页面没有刷新。这使得上传结束后,服务器处理结果返回到动态iframe窗口而没有刷新页面;
具体code,这里再也不枚举,感兴趣童鞋能够去 iframe+form 查看。数组

  • ajax + FormData 形式

哎呀,终于来到了现代社会,而且见到了我们的主角 FormData。 ajax 你们确定都知道了,异步刷新,无需从新加载整个网页的状况下,便可以更新部分网页。
那FormData 是什么呢? FormData是XMLHttpRequest Level 2添加的一个新接口,他能够 构建相似表单的键值对, 也就是说咱们能够利用 FormData 来模拟表单控件,而后使用XMLHttpRequest的send()
方法来异步的提交这个"表单"。
看一下简单的使用 FormData传文件的例子浏览器

<body>
    <input type="file" id="upload" name="upload" />    
    <input type="button" value="提交"  onclick="demoUpload()" />
    <script type="text/javascript">
        function demoUpload() {
            console.log('submit');
            var myFile = document.getElementById('upload').files[0];
            var xhr = new XMLHttpRequest();
            var formData = new FormData();
            var url = 'http://hqy.qunar.com:8080/';
            // for (var key in params) {    
            //     formData.append(key, params[key]);
            // }
            formData.append('uploadFile', myFile); // 文件
            formData.append('name', 'qunar');  // 其它数据
            xhr.open('POST', url, true);  //这里的url为本地起的一个服务地址
            xhr.send(formData);
        }
    </script>
</body>

选择文件并上传后,经过浏览器看看网络状况。

答案

啰啰嗦嗦这么多,终于知道了为何传文件要用FormData了!!开心,简单来讲就是,传文件一开始设计使用 form 来传,可是呢,使用form默认的上传方式存在诸多问题,好比同步啦,我想在上传以前处理一下数据啦,这个时候FormData 就站出来了,大喊 我能够构建相似表单的键值对,来模拟表单,发送的数据用我构建的对象就能够上传文件了。今后咱们上传文件就欢欣鼓舞的来找FormData了。
好了,另外一个小问题,文件和其余数据的不一样,文件传输时是二进制数据,因此格式和通常数据不同。 咱们的FormData大侠不只能够传文件也能够传通常数据哦,固然传输数据有不少种方式,好比get请求的时候跟在url后面。

2. 请求为何要用fetch呢? 和过气网红Ajax 什么关系?和xhr 有什么关系呢?

认真看过问题1的回答,这个问题就很简单了。fetch api 是一个提供请求资源(包括经过网络)的接口,它和xhr(XMLHttpRequest)相似。
因此请求不是为何要用fetch,而是fetch 只是一种方法,能够用fetch也能够用xhr(参考问题一中的 ajax + FormData demo),他们逻辑上是‘并列’的。
至于问和AJAX 什么关系,不如说 Ajax 和 xhr什么关系。由于Ajax的核心是XMLHttpRequest对象, Ajax异步的实现是经过new 一个 XMLHttpRequest对象,通常简称该对象对xhr。因此这里 fetch 是Ajax或XMLHttpRequest的一个替代方案。

3. 为何传文件的时候,'content-type'不能指定 'multipart/form-data' 呢?

当指定为'multipart/form-data'的时候,还须要指定 boundary=something。若是不指定则会自动分配。

ps: 这些回答基于本身理解,若有不妥,但愿路过的大神轻喷,指正。

FormData

MDN上这样解释FormData:
The FormData interface provides a way to easily construct a set of key/value pairs representing form fields and their values, which can then be easily sent using the XMLHttpRequest.send() method.It uses the same format a form would use if the encoding type were set to "multipart/form-data".
FormData 接口提供了一种方法,能够方便地构造一组表示表单字段和它们的值的键值对,而后可使用XMLHtRPROQuest.send()方法轻松发送。若是一个表单设置编码格式为 multipart/form-data, 这个表单将和FormData 使用相同的格式。

从头提及 FormData

XHR

fetch

MDN 这样介绍Fetch,Fetch API 是和XHR相似的用于获取资源(包括经过网络)的一种接口方法,可是 Fetch API提供了更强大更灵活的API。fetch()即是其中一个全局方法。

3.1 XHR(XMLHttpRequest) 和 fetch 什么关系?

Fetch和XHR平行关系,

3.2 fetch 和 FormData

先来看fetch()几种常见的用法:

Uploading JSON data: POST JSON-encoded data.

var url = 'https://example.com/profile';
var data = {username: 'example'};

fetch(url, {
  method: 'POST', // or 'PUT'
  body: JSON.stringify(data), // data can be `string` or {object}!
  headers:{
    'Content-Type': 'application/json'
  }
}).then(res => res.json())
.catch(error => console.error('Error:', error))
.then(response => console.log('Success:', response));

upload a file

var formData = new FormData();
var fileField = document.querySelector("input[type='file']");

formData.append('username', 'abc123');
formData.append('avatar', fileField.files[0]);

fetch('https://example.com/profile/avatar', {
  method: 'POST',
  body: formData
})
.then(response => response.json())
.catch(error => console.error('Error:', error))
.then(response => console.log('Success:', response));
相关文章
相关标签/搜索