1. 案例介紹
使用前後端分離開發的模式實作檔案上傳,前端使用Vue架構,後端使用node的express架構,并且顯示上傳進度條。
案例效果:
2. 核心代碼
2.1 環境搭建
前端環境
# 安裝Vue腳手架
cnpm i -g @vue/cli
# 建立項目
vue create myapp
# 進入項目目錄
cd myapp
# 安裝axios
cnpm i axios --save
# 啟動項目
npm run serve
後端環境
# 安裝express腳手架
cnpm i -g express-generator
# 建立項目
express upload-demo
# 進入項目目錄
cd upload-demo
# 安裝multer子產品
cnpm i multer --save
# 啟動項目
npm start
因為要同時在本地啟動前端和後端的服務,是以把前端服務端口改成
8080
,後端服務端口改成
3000
2.2 前端核心代碼
建立檔案 views/Main.vue
<template>
<div>
<div>
<input type="file" @change="fileSelect($event)" />
<button @click="fileSubmit">上傳</button>
</div>
<div class="progress-wrap">
<p>上傳進度</p>
<p class="progress"><span :style="style"></span></p>
</div>
</div>
</template>
<script>
export default {
data(){
return {
file: {}, //上傳的檔案對象
progressBar: 0 // 記錄上傳進度的變量
}
},
computed:{
style(){ // 進度條樣式
return {
width: this.progressBar+"%"
}
}
},
methods:{
fileSelect(e){
this.file = e.target.files[0]
},
async fileSubmit(){
const formData = new FormData();
formData.append('file',this.file);
await this.$axios.post('http://localhost:3000/file/upload',formData,{
onUploadProgress: (progressEvent)=>{
var percentCompleted = Math.round( (progressEvent.loaded * 100) / progressEvent.total );
this.progressBar = percentCompleted
}}).then(res=>{
console.log(res.data)
})
}
}
}
</script>
<style>
.progress-wrap {
width: 300px;
}
.progress-wrap p {
width: 100%;
}
.progress {
background-color: #c5c8ce;
height: 20px;
}
.progress span {
display: block;
background-color: #19be6b;
height: 100%;
width: 0;
}
</style>
2.3 後端核心代碼
建立路由檔案 routes/upload.js
let express = require('express')
let router = express.Router()
let multer = require('multer')
let fs = require('fs');
let path = require('path');
let upload = multer({
storage: multer.diskStorage({
//設定檔案存儲位置
destination: function(req, file, cb) {
let date = new Date();
let year = date.getFullYear();
let month = (date.getMonth() + 1).toString().padStart(2, '0');
let day = date.getDate();
let dir = "./uploads/" + year + month + day;
//判斷目錄是否存在,沒有則建立
if (!fs.existsSync(dir)) {
fs.mkdirSync(dir, {
recursive: true
});
}
//dir就是上傳檔案存放的目錄
cb(null, dir);
},
//設定檔案名稱
filename: function(req, file, cb) {
let fileName = file.fieldname + '-' + Date.now() + path.extname(file.originalname);
//fileName就是上傳檔案的檔案名
cb(null, fileName);
}
})
});
router.post('/upload', upload.single('file'), (req, res) => {
res.json({
file: req.file
})
})
module.exports = router
post請求的中間件
upload.single('file')
中的參數要和前端
formData.append('file',this.file);
中的鍵名保持一緻。
2.4 上傳案例示範
分别啟動前端服務和後端服務,在浏覽器中通路前端服務位址:
http://localhost:8080