node上传文件 + vue3 + elementPlus 组件封装

一、node

1.在node环境中安装multer(node.js中间件)包,用于处理 multipart/form-data 类型的表单数据

 npm install --save multer

2.userRouter

var express = require('express');
const multer  = require('multer')
const upload = multer({ dest: 'public/avataruploads/' })

const UserController =  require('../../controllers/admin/UserController');

var router = express.Router();

// 上传图片接口                   
router.post('/adminapi/upload', upload.single('file'), UserController.upload);

module.exports = router;

public/avataruploads/  :上传后存放的路径地址

upload.single('file') :中的file是前端传过来的file文件的键

3.UserController.upload

const UserController = {
    // 上传图片
    upload: async (req, res, next) => { 
        console.log(req.file, 'req.file');
        res.send({code:200,msg:'上传成功',data:{url:'/avataruploads/' + req.file.filename}})
    }
}

module.exports = UserController;

二、Vue

1.upload组件
 

<template>
  <div>
    <!-- :auto-upload="false" -->
    <el-upload
      class="avatar-uploader"
      :action="baseURL + url"
      :headers="{ Authorization: useStore.token }"
      :show-file-list="false"
      :on-success="handleAvatarSuccess"
      :on-error="handleAvatarError"
    >
      <img v-if="imageUrl" :src="imageUrl" class="avatar" />
      <el-icon v-else class="avatar-uploader-icon"><Plus /></el-icon>
    </el-upload>
  </div>
</template>

<script setup lang="ts">
import { ElMessage, type UploadProps } from 'element-plus'
import { Plus } from '@element-plus/icons-vue'
import { baseURL, httpUrl } from '@/utils/request'
import { useUserStore } from '@/stores'
import { useRouter } from 'vue-router'

const router = useRouter()
const useStore = useUserStore()

const props = defineProps({
  file: {
    type: String,
    default: ''
  },
  url: {
    type: String,
    default:  '/adminapi/upload'
  }
})

const emit = defineEmits(['uploadSuccess'])

const imageUrl = ref('')

const handleAvatarSuccess: UploadProps['onSuccess'] = (response, uploadFile) => {
  console.log(response, uploadFile)
  if (response.code === 200) {
    imageUrl.value = response.data.url
    emit('uploadSuccess', response.data.url)
  } else {
    ElMessage.error(response.msg)
  }

  //   imageUrl.value = URL.createObjectURL(uploadFile.raw!)
}

const handleAvatarError: UploadProps['onError'] = (err: Error, uploadFile) => {
  if (err.status === 401) {
    ElMessage.error('登录已过期,请重新登录')
    useStore.delUser()
    return router.replace('/login')
  }
  console.dir(err, uploadFile)
}

watch(imageUrl, (newUrl) => {
  if (newUrl && !newUrl.includes('http')) {
    imageUrl.value = httpUrl + newUrl
  }
})

watch(
  () => props.file,
  (newFile) => {
    imageUrl.value = newFile
  },
  { immediate: true }
)
</script>

<style scoped>
.avatar {
  width: 178px;
  height: 178px;
  display: block;
}
</style>

利用watch监听了数据的变化 拿到地址并不是带域名的(防止部署服务器时,图片丢失问题)所以更改后把配置后的域名给带上

2. 使用upload组件

<template>
  <Upload :file="ruleForm.avatar" @uploadSuccess="uploadSuccessHandler"></Upload>
</template>

<script lang="ts" setup>

const ruleForm = reactive<RuleForm>({
  avatar: ''
})


const uploadSuccessHandler = (url: string) => {
  console.log(url)
  ruleForm.avatar = url
}

</script>

猜你喜欢

转载自blog.csdn.net/m0_46846526/article/details/132142221