【vue3】图片上传功能实现

本次功能使用的是vue3+elementplus+nodejs+multiparty实现的图片上传与使用。

属于自行摸索的部分,有很大改进地方。目前思路是图片和数据分别上传,在上传图片时返回图片地址,将地址保存到表单数据中,在获取图片时,通过地址读取图片。

问题点:图片添加后就直接会上传,导致重复。

一、前端部分

引入部分自行引入,地址:快速开始 | Element Plus (element-plus.org)

新建ceshi.vue

<el-form :model="form" label-width="auto" style="max-width: 800px">
<el-form-item label="上传封面">
			<el-upload drag class="avatar-uploader" method="post" action="/api/image" :show-file-list="false"
				:on-success="handleAvatarSuccess" :before-upload="beforeAvatarUpload">
				<img v-if="form.imgUrl" :src="`http://127.0.0.1:3000/getimg?url=${form.imgUrl}`" class="avatar" />
				<div v-else>
					<el-icon class="avatar-uploader-icon">
						<Plus />
					</el-icon>
					<div class="el-upload__text"> 上传文章封面图,可将图片拖到此处 或 <em>点击上传</em>
					</div>
				</div>
			</el-upload>
		</el-form-item>
</el-form>
<script lang="ts" setup>
import { ref } from 'vue'
import { ElMessage } from 'element-plus'
import { Plus } from '@element-plus/icons-vue'

import type { UploadProps } from 'element-plus'

// do not use same name with ref
	let form = ref({
		title: '',
		desc: '',
		html: '',
		categoryName: '',
		imgUrl: ''
	})
const imageUrl = ref('')
	//图片上传成功的钩子
	const handleAvatarSuccess : UploadProps['onSuccess'] = (
		response,
		uploadFile
	) => {
		imageUrl.value = URL.createObjectURL(uploadFile.raw!)
		form.value.imgUrl=response
	}
	//上传图片组件->上传图片之前触发的钩子函数
	const beforeAvatarUpload : UploadProps['beforeUpload'] = (rawFile) => {
		const allowedFormats = ['image/jpeg', 'image/png']; // 允许的文件格式
		 if (!allowedFormats.includes(rawFile.type)) {
		        this.$message.error('文件格式必须是 JPG 或 PNG!');
		        return false;
		    }
		 else if (rawFile.size / 1024 / 1024 > 2) {
			ElMessage.error('Avatar picture size can not exceed 2MB!')
			return false
		}
		return true
	}
</script>

二、后端部分

1.新建文件夹,在命令行输入express -e account(文件夹名称),即可创建项目。

在routers下index.js中----添加图片api


const multiparty = require('multiparty')

//添加图片
router.post('/image', function(req, res, next) {
	//添加图片的位置
	let form =new multiparty.Form({uploadDir:'./public/images'})
	form.parse(req, function(err, fields, files) {
		//返回图片的地址
		  res.json(files.file[0].path)
	});
});

获取图片的api

//获取图片
router.get('/getimg', (req, res, next) => {
	//获取图片地址
	let url=req.query.url
	//返回图片
	fs.readFile(`./${url}`,(err,data)=>{
		res.send(data)
	})
})

完整

var express = require('express');
var moment = require('moment');
var router = express.Router();
const fs=require('fs')
const multer = require('multer');
const multiparty=require('multiparty')
const accountModel = require('../models/accountModels.js');

/* GET home page. */
router.get('/', function(req, res, next) {
  res.render('index', { title: 'Express' });
});

//获取全部文章信息账单
router.get('/getArticle', (req, res, next) => {
	 res.setHeader('Access-Control-Allow-Origin','*')
	accountModel.find().sort({createTime:-1}).then((data, err) => {
		if (err) {
			res.json({
				code: '1002',
				msg: '读取失败',
				data: null
			})
			return
		}
		res.json({
			code: '20000',
			msg: '找到了',
			data: data
		})


	});
})

//获取图片
router.get('/getimg', (req, res, next) => {
	//获取图片地址
	let url=req.query.url
	//返回图片
	fs.readFile(`./${url}`,(err,data)=>{
		res.send(data)
	})
})


//获取单个文章信息账单
router.get('/getArticle/:id', (req, res, next) => {
	let id = req.params.id
	
	accountModel.findById({
		_id: id
	}).then((data, err) => {
		
		if (err) {
			res.json({
				code: '1002',
				msg: '读取失败',
				data: null
			})
			return
		}
		res.json({
			code: '20000',
			msg: '找到了',
			data: data
		})


	});
})


//添加文章
router.post('/getArticle', function(req, res, next) {
	//插入数据库
	accountModel.create({...req.body,createTime:moment(req.body.createTime).toDate()}).then((data, err) => {
		if (err) {
			res.json({
				code: '1001',
				msg: '读取失败',
				data: null
			})
			return
		}
		res.json({
			code: '20000',
			msg: '读取成功',
			data: data
		})
	})

});

//添加图片
router.post('/image', function(req, res, next) {
	//添加图片的位置
	let form =new multiparty.Form({uploadDir:'./public/images'})
	form.parse(req, function(err, fields, files) {
		//返回图片的地址
		  res.json(files.file[0].path)
	});
});



//更新文章
router.patch('/getArticle/:id', function(req, res, next) {  
    // 获取id参数  
    const id = req.params.id;  
  
    // 假设你有一个 bodyParser 或类似的中间件来解析请求体  
    // 这里的 req.body 应该包含你想要更新的字段  
    const updateData = req.body; // 例如: { title: '新标题', content: '新内容' }  
  console.log(updateData);
    // 使用 updateOne 更新文档  
    accountModel.updateOne({  
        _id: id  
    }, {  
        $set: updateData // 使用 $set 操作符来更新字段  
    }).then(result => {  
        // result 包含 matchedCount 和 modifiedCount  
        if (result.modifiedCount === 0) {  
            // 如果没有文档被修改(可能是因为没有找到对应的 _id)  
            res.json({  
                code: '1002',  
                msg: '未找到或未更新任何文档',  
                data: null  
            });  
        } else {  
            // 如果想要返回更新后的文档,可以使用 findByIdAndUpdate 并设置 new: true  
            accountModel.findById(id, { new: true }).then(updatedDoc => {  
                res.json({  
                    code: '20000',  
                    msg: '更新成功',  
                    data: updatedDoc  
                });  
            }).catch(err => {  
                // 处理 findById 的错误  
                res.json({  
                    code: '1003',  
                    msg: '获取更新后的文档失败',  
                    data: null  
                });  
            });  
        }  
    }).catch(err => {  
        // 处理 updateOne 的错误  
        res.json({  
            code: '1001',  
            msg: '更新失败',  
            data: null  
        });  
    });  
});

//删除文章
router.delete('/getArticle/:id', function(req, res, next) {
	//获取id参数
	let id = req.params.id
	accountModel.deleteOne({
		_id: id
	}).then((data, err) => {
	
			if (err) {
				res.json({
					code: '1002',
					msg: '读取失败',
					data: null
				})
				return
			}
			res.json({
				code: '20000',
				msg: '读取成功',
				data: data
			})
		})
	
	});

module.exports = router;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值