一、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-uploadclass="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.urlemit('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>