## 使用 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);
```