nodejs图片上传/头像上传

项目结构

在这里插入图片描述
utils文件夹无用,没文件

前端代码

<!DOCTYPE html>
<html lang="zh-CN">
	<head>
		<meta charset="utf-8" />
		<meta http-equiv="X-UA-Compatible" content="IE=edge" />
		<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no" />
		<meta name="author" content="金西振" />
		<title></title>
		<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
		<style></style>
	</head>
	<body>
		<form>
			<!-- multiple 属性支持选择多个文件 -->
			<!-- accept="image/*" 只能选择图片 -->
			<input type="file" name="myfile" id="myfile" accept="image/*" multiple />
			<br />
			<input type="submit" value="上传" />
		</form>
		<script>
			const form = document.forms[0];
			const input = form.myfile;
			form.onsubmit = function (ev) {
				ev.preventDefault();
				// input.files获取选择的文件
				// console.log('文件上传 input.files', input.files);

				const file = input.files[0];
				console.log('file: ', file);
        if (!file) {
          return alert('请选择图片');
        }
				// 如果不是图片提示用户修改
				if (!file.type.startsWith('image')) {
					return alert('只能上传图片');
				}

				// 方式一:使用append;
				// const formdata = new FormData();
        // 上传一个文件
				// formdata.append('myfile', file);

        // 上传多个文件
				// formdata.append('myfile', input.files[0]);
				// formdata.append('myfile', input.files[1]);
				// formdata.append('myfile', input.files[2]);


				// 方式二:传递form对象:单个和多个文件写法一致
				const formdata = new FormData(form);

				axios({
					url: 'http://127.0.0.1:3000/upload',
					method: 'POST',
					data: formdata,
				}).then(({ data }) => {
					console.log('data: ', data);
				});
			};
		</script>
	</body>
</html>

app.js代码

const express = require('express');
const cors = require('cors');

const app = express();
app.use(cors());
app.use(express.json());
app.use(express.urlencoded({ extended: false }));

app.use(require('./router/upload'));

app.listen(3000, () => {
	console.log('running: http://127.0.0.1:3000');
});

// 文件上传
// 服务端(听懂即可):需要使用multer模块

// 客户端(掌握):只需要使用post请求,发送formdata类型的数据即可

upload核心代码:

const router = require('express').Router();
const multer = require('multer');
const path = require('path');
// 获取文件的扩展名
console.log(path.extname('1.png'));

const storage = multer.diskStorage({
	// 用来指定文件的位置
	destination(req, file, cb) {
		cb(null, './public/img');
	},
	// 用来设置文件的名字
	filename(req, file, cb) {
		// console.log('file: ', file);
		const filename = Date.now() + path.extname(file.originalname);
		cb(null, filename);
	},
});

// {
//   fieldname: 'myfile',     上传时定义的名字
//   originalname: 'head.png',  图片名字
//   encoding: '7bit',     编码格式
//   mimetype: 'image/png'    文件类型
// }

const upload = multer({
	// 使用dest选项无法修改文件的名,文件名默认是一个长度为32位的随机值
	// dest: './public/img',
	storage: storage,
	// 文件上传限制:单位字节
	limits: { fileSize: 1024 * 1024 * 2 },
	// 文件过滤:决定哪些文件可以上传,哪些文件跳过
	// fileFilter: function (req, file, cb) {
	// 	if (file.mimetype.startsWith('image')) {
	// 		cb(null, true); // 接收这个文件
	// 	} else {
	// 		cb(null, false); // 拒绝这个文件
	// 	}
	// },
});

// multer模块是用来专门处理文件上传的,只处理multipart/form-data类型的数据
// 使用formdata可以传递文本信息,也可以传递文件数据
// 如果传递文本数据,会把参数数据保存在req.body中
// 如果传递文件数据,会把参数数据保存在req.file 或者 req.files 中

// 使用multer模块,会向req对象上添加body和 file或者files属性
// req.body 用来获取文本信息
// req.file 单个文件上传的信息  upload.single('myfile') 用上传单个文件
// req.files 一次上传多个文件的信息 upload.array('myfile', 6) 用于上传多个文件
// myfile是参数名,类似于username
router.post('/upload', upload.array('myfile'), (req, res) => {
	console.log('req.files:', req.files);

	// if (req.file) {
	res.json({ error: 0, data: '上传成功' });
	// } else {
	// 	res.json({ error: 0, data: '上传失败' });
	// }
});

module.exports = router;

头像上传数据库(这里只写后端核心代码)

const express = require('express');
const multer = require('multer');
const fs = require('fs');
const path = require('path');

let User = require('../modules/user');
let router = express.Router();
const jwt = require('../modules/jwt');

let uploadpath = './public/imgs/'; // 图头像上传地址
const imgURL = './imgs/'; // 头像网路地址
let avatarName; // 头像名字

let storage = multer.diskStorage({
	destination: function (req, file, cb) {
		cb(null, uploadpath);
	},
	filename: function (req, file, cb) {
		let extname = path.extname(file.originalname);
		// 张三-1834137249801230921.png
		avatarName = req.username + '-' + Date.now() + extname;
		cb(null, avatarName);
	},
});
let isImage = false;
let upload = multer({
	storage: storage,
	limits: {
		fileSize: 1024 * 1024 * 5,
	},
	fileFilter: function (req, file, cb) {
		if (file.mimetype.startsWith('image')) {
			isImage = true;
			cb(null, true);
		} else {
			isImage = false;
			cb(null, false);
		}
	},
});

router.post('/user/avatar', jwt.verify, upload.single('avatar'), (req, res) => {
	if (!isImage) {
		res.json({ error: 1, data: '只能上传图片' });
		return;
	}
	// 如果现在的头像不是默认图片,删除现有的头像(旧头像),保存新上传的头像地址
	if (fs.existsSync(uploadpath + avatarName)) {
		User.findOne({ _id: req._id }, (error, user) => {
			// 如果用户有旧头像,则先删除旧头像文件,然后把新头像文件的url存入用户信息
			if (user.avatar != imgURL + 'timg.jpg') {
				let oldpath = user.avatar.replace(imgURL, 'public/imgs/');
				if (fs.existsSync(oldpath)) {
					fs.unlinkSync(oldpath); //删除旧头像
				}
			}
			// 保存新头像
			user.avatar = imgURL + avatarName; //新头像的地址
			user.save(error => {
				res.json({ error: 0, data: '上传成功' });
			});
		});
	} else {
		res.json({ error: 0, data: '上传失败' });
	}
});

module.exports = router;

JWZ权限验证代码

const jwt = require('jsonwebtoken');
const secretkey = 'howdoyoudo'; //密钥

// 生成token
module.exports.sign = (data = {}) => {
	return jwt.sign(data, secretkey, {
		expiresIn: 60 * 60,
	});
};

// 验证token
module.exports.verify = (req, res, next) => {
	let authorization = req.headers.authorization || req.body.token || req.query.token || '';
	let token = '';
	if (authorization.includes('Bearer')) {
		token = authorization.replace('Bearer ', '');
	} else {
		token = authorization;
	}

	jwt.verify(token, secretkey, (error, data) => {
		if (error) {
			res.json({ error: 1, data: 'token验证失败' });
    } else {
			req._id = data._id;
			req.username = data.username;
			next();
		}
	});
};
  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

萧寂173

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值