欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Vue + ElementUI + ExpressJS实现上传头像的功能

程序员文章站 2022-05-01 21:51:13
...

前端代码

1. 首先我们需要用到elementUI的upload组件

<el-upload
   class="avatar-uploader"
    :show-file-list="false"
    :http-request='uploadAvatar' 
    :before-upload="beforeAvatarUpload">
    <img v-if="imageUrl" :src="imageUrl" class="avatar">
    <i v-else class="el-icon-plus avatar-uploader-icon"></i>
</el-upload>
  • http-request钩子函数:可以覆盖默认的上传行为,可以自定义上传的实现。
  • brfore-upload钩子函数:在文件上传前进行操作,比如判断是否符合要求。

2. 实现brfore-upload钩子函数

beforeAvatarUpload(file) {
  this.file = file
  this.fileName = file.name
  this.fileType = file.type
  const isImage = file.type === 'image/jpeg' || file.type === 'image/png' || file.type === 'image/gif'
  const isLt2M = file.size / 1024 / 1024 < 2;

  if (!isImage) {
    this.$message.error('上传头像图片只能是 JPG | PNG | GIF 格式!');
  }
  if (!isLt2M) {
    this.$message.error('上传头像图片大小不能超过 2MB!');
  }
  return isImage && isLt2M;
},
  • 如上图代码所示,我们规定了只能是三种格式,并且大小不能超过2MB

3. 实现http-reuqest钩子函数

uploadAvatar() {
  // 使用formData进行文件上传
   let formData = new FormData()
   formData.append('fileName', this.fileName) // 文件名字
   formData.append('file', this.file) // 当前文件
   formData.append('name', this.$store.getters.userInfo.name) // 当前登录的用户的名字
   formData.append('staff_num', this.getStaffNum) // 当前登录用户的员工编号,在数据库查找时会用到
   formData.append('host', `//${window.location.hostname}:5000`) // 把当前主机名传过去,后端利于拼接并且存放在数据库

   let url = 'http://localhost:5000/api/avatar/uploadAvatar'
   let xhr = new XMLHttpRequest()
   xhr.onreadystatechange = () => {
     if (xhr.readyState === 4 && xhr.status === 200) {
       let res = JSON.parse(xhr.responseText)
       this.$message.success(`${res.data.msg}`)
       let dominName = window.location.hostname
       this.getUser.avatar = `//${dominName}:5000${res.data.fileUrl}` // 这一步的目的是把vuex里存放的avatar的值也改变
       let user = this.getUser
       this.$store.dispatch('setUserInfo', user) // 更新vuex
       setTimeout(() => {
         location.reload() // 300ms之后,刷新页面。否则上传图像之后它不会自动改变
       }, 300)
     }
   }
   xhr.open('post', url)
   xhr.setRequestHeader('Authorization', localStorage.jwtToken) // 由于后端使用了jwt验证。所以这里要设置一下请求头
   xhr.send(formData)

总结一下:文件上传必须使用formData。请求方法可以用jQuery的ajax,也可以使用xmlHttpRequest。本文使用的就是xmlHttpRequest

后端代码

4. 安装forimidable来解析上传的文件

npm i forimidable --save

这时可能有同学会问,什么是forimidable?

formidable : Node.js模块,用于解析表单数据,特别是文件上传。

5. 解析图片

let form = new forimidable.IncomingForm()
form.uploadDir = path.join(__dirname, '../../public/avatars') // 设置静态资源路径
form.keepExtensions = true // 使用源文件的扩展名
form.parse(req, (err, fields, files) => {
  if (err) return res.json(err)
  let extName = '' // 文件后缀
  switch(files.file.type) { // 这一步的目的是设置文件后缀
    case 'image/jepg':
      extName = 'jpg'
      break
    case 'image/png':
      extName = 'png'
      break
    case 'image/gif':
      extName = 'gif'
      break
    default:
      extName = 'jpg'
      break
  }
  let avatarName = `${fields.name}'s_avatar.${extName}` // 根据传过来的用户名以及上面获取到的后缀名拼接出新的头像的名字
  let newPath = form.uploadDir + '/' + avatarName // 获取头像的路径
  fs.rename(files.file.path, newPath, (err) => {
  // 这一步是重命名,files.file.path是原始文件路径,newPath是上方拼接出来的。
  // 同时,重命名还可以避免同一用户上传多个文件。占用服务器资源。
    if (err) return res.json({data: {code: 400, msg: '操作失败'}})
	
	// 接下来是将图片地址更新到数据库~
    let update = {
      avatar: `${fields.host}/avatars/${avatarName}`
    }
    // 把图片地址更新到数据库
    User.findOneAndUpdate({name: fields.name, staff_num: fields.staff_num}, 
      {$set: update}, {new: true}).then(user => {
        res.json({data: {
          code: 200,
          msg: '操作成功',
        }})
    }).catch(err => res.json({data: {code: 500, msg: 'something error!'}}))
  })
})

tips:将头像地址存放到数据库仅仅是更新一下。前端使用的还是更新的vuex里面的数据。 如图 ↓
Vue + ElementUI + ExpressJS实现上传头像的功能

如果要部署到服务器怎么办?

服务器一般监听80端口,所以拼接地址的时候就不需要 ‘:5000’ 了

以上就是简单的实现上传头像功能。谢谢翻看~