FormData上傳檔案到伺服器
阿新 • • 發佈:2020-06-29
後端配置
上傳檔案一定是 post 請求,這裡我們使用 koa 實現一個簡易的 post 請求,並且讓獲取前端發來的 formdata 資料 並進行一些簡易的處理 ;
const Koa = require('koa');
const Router = require('koa-router');
const koaBody = require('koa-body');
let app = new Koa();
let router = new Router();
app.use(koaBody({
multipart: true // 允許客戶端上傳檔案
}));
router.post('/upload' ,async (ctx,next) => {
// 客戶端上傳的檔案會在這個物件中存在 ctx.request.files
// 讀取這個檔案,然後存到 upload 資料夾,實現簡易的儲存檔案功能
let data = fs.readFileSync(ctx.request.files.image.path);
fs.writeFileSync(path.join(__dirname,'upload',ctx.request.files.image.name),data);
ctx.body = { status: 1 };
});
app.use(router.routes());
app.listen(3000 );
複製程式碼
前端實現單檔案上傳
前端這裡使用 FormData 物件和 XMLHttpRequest 物件來實現檔案上傳
這裡咱們就先不考慮樣式了,只是簡單實現功能
<input type="file" />
<button>點選上傳</button>
複製程式碼
document.querySelector('button').onclick = function () {
// 這裡會獲取一個 files 陣列物件 因為是單檔案上傳取第一個即可
let file = document.querySelector('input').files[0];
let xhr = new XMLHttpRequest();
xhr.open('post','/upload',true);
xhr.onload = function () {
let res = JSON.parse(xhr.responseText);
console.log(res);
}
let form = new FormData();
form.append('image',file); // 對應 key value
xhr.send(form);
}
複製程式碼
到這裡,就已經實現了 檔案上傳並且通過服務端進行轉存 ; 需求怎麼可能這麼簡單就實現呢,我們可以再新增一些拓展,比如進度條,和上傳速度 ;
單檔案的上傳速度與進度條
html 優化部分 : 這裡進度條,我們就根據 html5 原生的 progress 標籤來實現 ;
<input type="file" />
<progress value="0" max="100"></progress>
<span class="percent">0 %</span>
<span class="speed">0 b/s</span>
<button>點選上傳</button>
複製程式碼
js 鋪墊 ; 這裡如果想要知道上傳的進度和當前下載的速度,我們肯定要辦到下面一些事情 ;
上傳檔案時的狀態監控
xhr.upload
下面有檔案上傳時的鉤子,我們可以利用這些鉤子函式實現進度條的監控
https://developer.mozilla.org/zh-CN/docs/Web/API/XMLHttpRequest/upload
獲取檔案的大小 total 獲取當前下載的大小 size
可以通過 鉤子函式中的 event 獲取到 total 和 size https://developer.mozilla.org/zh-CN/docs/Web/API/XMLHttpRequestEventTarget/onprogress
let startTime;
let startSize;
document.querySelector('button').onclick = function () {
// 這裡會獲取一個 files 陣列物件 因為是單檔案上傳取第一個即可
let file = document.querySelector('input').files[0];
let xhr = new XMLHttpRequest();
xhr.open('post',file); // 對應 key value
xhr.upload.onloadstart = function () {
// 開始上傳鉤子
startTime = new Date().getTime();
startSize = 0;
}
xhr.upload.onprogress = function (event) {
// 正在上傳鉤子,會被多次呼叫
// 已傳輸的資料量 / 總共的資料量 * 100
let percent = (event.loaded / event.total * 100).toFixed(0);
document.querySelector('progress').value = percent;
document.querySelector('.percent').innerHTML = percent + ' %';
let currentTime = new Date().getTime();
let dtime = (currentTime - startTime) / 1000; // 時間差 s
startTime = new Date().getTime(); // 計算完成後重新獲取時間
let dsize = event.loaded - startSize; // 大小差 b
startSize = event.loaded; // 計算完成後重新獲取帶下
let speed = dsize / dtime; // 速度
let unit = 'b/s'; // 單位
// 單位進位制計算
if (speed / 1024 > 1) {
speed = speed / 1024;
unit = 'kb/s';
}
if (speed / 1024 > 1) {
speed = speed / 1024;
unit = 'mb/s';
}
document.querySelector('.speed').innerHTML = speed.toFixed(2) + unit;
}
// 上傳完成後重置 進度條等
xhr.onload = function () {
document.querySelector('progress').value = 0;
document.querySelector('.percent').innerHTML = 0 + ' %';
document.querySelector('.speed').innerHTML = '0b/s';
}
xhr.send(form);
}
複製程式碼
axios 單檔案上傳帶進度條
axios 中監控進度,通過 onUploadProgress 鉤子來監控進度
axios.post('/upload',form,{
onUploadProgress: event => {
let complete = (event.loaded / event.total * 100 | 0)
document.querySelector('progress').value = complete;
document.querySelector('.percent').innerHTML = complete + ' %';
if (complete >= 100) {
document.querySelector('progress').value = '0';
document.querySelector('.percent').innerHTML = 0 + ' %';
}
},}).then(res => {
console.log(res)
});
複製程式碼
效果展示
本文使用 mdnice 排版