Vue + node.js(Express) 項目中實現換頭像與文件上傳
實現效果
上傳後
// html部分
<div class="head_img">
<img :src="userInfo.avatar"/>
</div>
<div class="setting_right" @click.stop="uploadHeadImg">
<div class="caption">更改頭像</div>
</div>
// display: none, 調用uploadHeadImg獲取到hiddenInput的dom執行點擊事件
<input type="file" accept="image/*" @change="handleFile" class="hiddenInput"/>
因爲input file的樣式不好改,所以直接display:none了,使用uploadHeaderImg操作DOM( 雖然Vue中不提倡 ), 但是香啊!!!
// Vue實例中
data () {
return {
userInfo: {
avatar: ''
}
}
}
methods: {
uploadHeadImg () {
// 實現隱藏被點擊的效果, 這樣就可以不用修改input的樣式
this.$el.querySelector('.hiddenInput').click()
},
handleFile (e) {
let $target = e.target || e.srcElement
// 獲取到上傳的file
let file = $target.files[0]
// 創建FileReader的實例用於讀取文件
let reader = new FileReader()
// 生成表單格式
let param = new FormData()
// 加入參數字段
param.append('file', file)
param.append('userId', localStorage.getItem('userId'))
// 無法直接查看param,可以用get的方法查看
console.log(param.get('file'))
console.log(param.get('userId'))
// axios請求
axios.post('/api/user/addImg', param, {
// application/x-www-form-urlencoded:默認編碼方式
// multipart/form-data: 設置指定傳輸數據爲二進制數據,例如圖片、mp3、文件
// text/plain:純文本的傳輸。空格轉換爲“+”,但不支持特殊字符編碼。
headers: { 'Content-Type': 'multipart/form-data' }
}).then(res => {
// 後端文件存儲完成後再進行圖片的讀取操作
// 讀取file文件作爲base64格式
reader.readAsDataURL(file)
})
// 讀取成功的操作 ( 更換頭像 )
reader.onload = data => {
let res = data.target || data.srcElement
// res.result 爲圖片的base64格式, 直接放入img標籤的src中即可
this.userInfo.avatar = res.result
}
// 讀取失敗的操作
reader.onerror = (e) => {
console.log('error' + e)
}
}
}
// 安裝 multer 模塊
npm i multer -S
// 安裝 fs 模塊
npm i fs -S
// 引入模塊
const express = require("express");
router = express.Router();
const multer = require('multer')
const upload = multer({dest: 'uploads/'}) // 配置圖片文件的路徑(沒有後綴名)
const fs = require('fs')
因爲multer模塊的上傳的圖片沒有後綴名,無法正常顯示
我們可以通過req.file獲取到文件的對象參數以及後綴名type,對文件進行拼接處理
// Express中 ( /api/user )
const express = require("express");
router = express.Router();
const multer = require('multer') // 引入 multer模塊
const upload = multer({dest: 'uploads/'}) // 配置圖片文件的路徑(沒有後綴名)
router.post('/addImg',upload.single('file'), (req, res, next) => {
// 獲取到file的信息 ---> 只能通過req.file
let fileObj = req.file
// 獲取到body中userId信息
let { userId } = req.body
// 分割出type
let originalArr = fileObj.originalname.split('.')
// 獲取到type ( jpg/png/gif )
let type = originalArr[originalArr.length - 1]
// 讀取文件 ( path, 'utf-8'(這裏不寫解碼類型,直接把回調函數中的data寫入新文件即可), callback)
fs.readFile('uploads/' + fileObj.filename, (err, data) => {
if (err) throw err
// 創建複製圖片的路徑 以及 拼接type形成一個完整的圖片文件
let newPath = '/img/headerImg/' + fileObj.filename + "." + type
// 寫入複製的圖片 (path, data, callback)
fs.writeFile('public' + newPath, data, (err) => { // 把讀取到的data寫入
if (err) throw err
// 刪除原uploads路徑下的圖片
fs.unlink('uploads/' + fileObj.filename, () => {
res.send({
code: '200',
msg: '上傳成功'
})
})
})
})
})
module.exports = router;
當然在配置multer的路徑的時候也可以直接配置需要存放的路徑
然後用fs模塊來修改文件的格式即可
const multer = require('multer') // 引入multer模塊
const upload = multer({dest: 'public/img/headerImg'}) // 存放的路徑
router.post('/addImg',upload.single('file'), (req, res, next) => {
// 獲取到file的信息 ---> 只能通過req.file
let fileObj = req.file
// 獲取到body中userId信息
let { userId } = req.body
// 分割出type ( jpg/png/gif )
let originalArr = fileObj.originalname.split('.')
let type = originalArr[originalArr.length - 1]
// rename的參數1: 原文件的路徑和文件名(沒有後綴名無法顯示)
// 參數2: 修改後的文件路徑和文件名(有後綴名可以顯示)
// 參數3: 回調函數
fs.rename('public/img/headerImg' + fileObj.filename, 'public/img/headerImg' + '.' + type, err => {
if (err) throw err
res.send({
code: '200',
msg: '上傳成功'
})
})
})
然後就可以顯示啦
當然在項目中後端還需要加入數據庫的操作,這裏沒有在接口中寫出來
把服務器中的路徑存入數據庫中,隨後每次讀取數據庫中的路徑放入src中就可以實現完整的效果了