nodejs实现文件/头像上传

文章介绍了在Node.js环境中使用multer中间件处理multipart/form-data格式的数据,用于文件上传。multer处理表单数据,存储文件,并提供了过滤和限制功能。客户端需使用POST请求和multipart/form-data数据格式。示例代码展示了如何配置multer进行图片上传,并更新用户头像。
摘要由CSDN通过智能技术生成

文件上传

文件上传就是把图片、音视频等文件上传到服务端,文件上传必须使用post请求,数据格式为multipart/form-data的数据。

服务端

在nodejs中处理文件,需要使用multer模块来处理multipart/form-data格式的数据。

Multer 是一个 node.js 中间件,用于处理 multipart/form-data 类型的表单数据,它主要用于上传文件。

注意: Multer 不会处理任何非 multipart/form-data 类型的表单数据。

中文文档:https://github.com/expressjs/multer/blob/master/doc/README-zh-cn.md

安装multer

npm install --save multer

使用

Multer 会添加一个 body 对象 以及 filefiles 对象 到 express 的 request 对象中。 body 对象包含表单的文本域信息,filefiles 对象包含对象表单上传的文件信息。

const multer = require('multer');


const uploadPath = './public/imgs';

const storage = multer.diskStorage({
	// destination 是用来确定上传的文件应该存储在哪个文件夹中
	destination: function (req, file, cb) {
		cb(null, uploadPath);
	},
	// filename 用于确定文件夹中的文件名的确定。 如果没有设置 filename,每个文件将设置为一个随机文件名,并且是没有扩展名的。
	filename: function (req, file, cb) {
		cb(null, Date.now() + '-' + file.originalname);
	},
});

const upload = multer({
	// 设置上传的文件存储位置
	storage: storage,
	// 文件上传限制:单位字节
	limits: { fileSize: 1024 * 1024 * 2 },
	// 文件过滤:决定哪些文件可以上传,哪些文件跳过
	fileFilter: function (req, file, cb) {
		if (file.mimetype.startsWith('image')) {
			cb(null, true); // 接收这个文件
		} else {
			cb(null, false); // 拒绝这个文件
		}
	},
});

//设置post请求处理图片上传
// upload.single(name) 单个文件上传
// upload.array(name,maxCount) 多个文件上传:name参数是文件选择input框的name属性,maxCount 最大上传数量
router.post('/upload', upload.single('myfile'), function (req, res) {
	// multer将请求中的文件存储之后,会把文件的信息(包括文件存储时的文件名)放入req.file对象中。(如果用的是upload.array,则会放在req.files中)
	// multer还会把本次表单提交的文本字段(如果有)解析为对象存入req.body中
	// console.log('文件:',req.file);
	if (req.file) {
		res.json({ error: 0, data: '上传成功' });
	} else {
		res.json({ error: 0, data: '上传失败' });
	}
});

客户端

文件上传必须使用post请求,数据使用 multipart/form-data 类型的表单数据。

有如下HTML结构

<form>
  <div id="upload-box">
    <img class="img" src="./imgs/add.png">
    <input class="upfile" type="file" name="myfile" accept="image/*" hidden>
  </div>
  <input class="upload" type="button" value="上传">
</form>
// 因为默认的input[type=file]标签长的丑,所以我们把它隐藏掉,但是依然保留其click的功能。
// 当点击div时,调用input[type=file]标签的click()方法,即可打开选择文件对话框
$("#upload-box").on("click", ".img", function () {
  $(this).next().click();
});

//显示图片(添加显示图片的代码)
var file = null;
$("#upload-box").on("change", ".upfile", function () {
  file = this.files[0];
  if (!file.type.startsWith('image')) {
    layer.msg('只能上传图片')
    file = null;
    return;
  }
  $('.upfile').prev().attr("src", URL.createObjectURL(file));
});

$('.upload').click(function (ev) {
  if (!file) {
    return alert('请选择图片')
  }

  var data = new FormData($('form').get(0));
  axios({
    url: '/upload',
    method: 'POST',
    data: data,
  }).then(res => {
    layer.msg(res.data.data)
  })
});

头像系统

/user.js

const mongoose = require('./db');

const userSchema = new mongoose.Schema({
  username:String,
  password:String,
  age:Number,
  gender:Number,//0 男;1 女
  major:String,
  hobby:Array,
  avatar:{
    type:String,
    // 默认值
    default:'http://127.0.0.1:3000/imgs/timg.jpg'
  }
});

let User = mongoose.model('user-avatar',userSchema);

module.exports = User;
//upload.js

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 = 'http://127.0.0.1:3000/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;
  • 0
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

萧寂173

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

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

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

打赏作者

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

抵扣说明:

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

余额充值