## 使用 FormData 文件上传
\[[不使用 FormData 做文件上传](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/Using_XMLHttpRequest#Submitting_forms_and_uploading_files)\]([https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/Using\_XMLHttpRequest#Submitting\_forms\_and\_uploading\_files](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/Using_XMLHttpRequest#Submitting_forms_and_uploading_files))
### 使用 FormData 封装文件参数
```
var formData = new FormData();
formData.append('username', 'Groucho');
formData.append('password', 123456); // 数字 123456 会被立即转换成字符串 '123456'
// file 类型 input
formData.append('userfile', document.getElementById("fileId").files[0]);
// 上面步骤的等价于自己定义表单元素,里面有对应 input,再通过表单元素来创建 FormData 对象
// JavaScript 创建文件
/*
var content = '<a id="a"><b id="b">hey!</b></a>'; // 新文件的内容
var blob = new Blob([content], { type: 'text/xml'});
formData.append("webmasterfile", blob);
*/
```
### 代码实现
需求:文件上传。
* 修改页面:
```
<span id="result"></span>
<form id='loginForm'>
<input type="text" id="username" name="username" placeholder="用户名">
<input type="text" id="password" name="password" placeholder="密码">
<input type="file" id="foo" name="foo">
<input id="login" type="button" value="登录">
</form>
```
修改 AJAX 代码
```
window.onload = function(){
var loginEle = document.querySelector('#login');
loginEle.onclick = function(){
// 使用 FormData 来处理参数数据
var formData = new FormData(document.querySelector('#loginForm'));
var ajax = new XMLHttpRequest();
ajax.open('post', '/profile', true);
// 发送信息至服务器时内容编码类型,默认为 'multipart/form-data'
ajax.onload = function () { // 当 xhr.readyState = 4 执行回调函数 2.0
if(ajax.status == 200 ) {
document.getElementById('result').innerText = ajax.responseText;
}
}
ajax.send(formData);
}
}
```
编写后台代码
```
const express = require('express');
const fileUpload = require('express-fileupload');
const path = require('path');
const app = express();
app.use(fileUpload());
app.use(express.urlencoded());
app.use('/static', express.static(path.join(__dirname, 'static')));
app.post('/profile', (req, res) => {
console.log(req.files.foo) // foo 是上传表单 file input 名称
console.log(req.body);
let f = req.files.foo;
f.mv(path.join(__dirname, 'static', 'upload', 'a.png'), function(err) {
if(err){
return res.status(500).send(err);
}
res.send('文件上传成功!');
});
});
app.listen(8888, () => {
console.log('running...');
});
```
思考: 文件上传时出现同名文件覆盖问题怎么解决, 若上传成功, 把上传图片显示下方
```
f.name+Date.now()
```
# 文件上传度
ajax.upload.onprogress = function(e){
```
// console.log("\_\_\_\_\_\_\_\_\_\_\_\_");
// console.log(e);
if(e.lengthComputable){
// 这里打印,实际情况在页面显示即可
console.log("上传进度:", Math.floor(e.loaded / e.total \* 100) + "%");
}
```
}
# 请求超时
```
var ajax = new XMLHttpRequest();
ajax.open('GET', 'url', true);
ajax.timeout = 2000; // 设置超时时间,单位是毫秒
ajax.onload = function () {
// 请求完成。在此进行处理。
};
ajax.ontimeout = function (e) {
// XMLHttpRequest 超时。在此做某事。
};
ajax.send(null);
```