multer中间件的使用

为什么需要multer中间件?

  • 我们在做文件上传的时候经常在前端使用到form表单来提交数据,上传文件不比上传数据(字符串或数值,数组),文件一般是比较大的,以此,不能采取x-www-form-urlencoded将数据拼接到URL(GET请求)或者请求体(POST)请求,因为后端是无法处理文件的,它自能处理jsonx-www-form-urlencoded格式的数据,这是一种规定,因此,要想上传文件到后端,就必须使用enctype="multipart/form-data"属性下的form表单,由此引出能够让后端处理multipart类型数据的中间件 - multer

什么是multer

  • Multer 是一个 node.js 中间件,用于处理 multipart/form-data 类型的表单数据,它主要用于上传文件。它是写在 busboy 之上非常高效。

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

基本使用:

安装multer

npm install --save multer

引入multer

//引入multer中间件处理文件
const multer = require('multer')
//自动创建处理后的文件保存目录,同时可也可以指定拓展名
const upload = multer({ dest: 'uploads/' })

将前端传过来的数据保存到指定的文件夹中

/* ----- 前端发送post请求将form表单数据提交到'/user'接口 ---------------*/
//upload.single():将前端form表单(指定name)传过来的文件数据传入到multer指定创建的文件夹中
app.post('/user',upload.single('headpic'),(req,res)=>{
//输出即表示可以成功接收到数据,随后处理即可(存数据库还是怎样都行)
//multer中间件还为你的req中添加了一个file,里面以对象的形式存放着你传过来的文件数据
console.log(req.body,req.file);
// 对前端传过来的数据进行一个判断,到底有没有传文件过来(根据是否存在req.file来判断)
const headpic = req.file ? `/uploads/${req.file.filename}`:`/uploads/default.png`
/*
此时我们就可以将这个文件的路径名保存到数据库中,文件本身保存到服务器
后续我们想要删掉这些前端保存到服务端的文件仅需要引入fs模块进行操作即可
*/
})

重新展示数据

  • 前端发送ajax请求图片数据(保存到服务器的路径)再使用img标签的src属性来接受就行了
axios.get('/getuser').then(res=>{
var data = res.data.data
console.log(res.data);
// alert(res.data.msg)

// 将获取到的数据填入到tbody中
tbody.innerHTML = data.map(item=>`
<tr>
<td><img src="${item.headpic}" /></td>
</tr>
`).join('')

多文件上传(array(fieldname[, maxCount])):(请查看官方文档)

完整的代码展示:

  • 服务器(app.js)
/* ---------------------- 文件上传1 ------------------------------*/
// 引入必要的模块
const express = require('express')
// 创建服务器
const app = express();
const mysql = require('mysql2')//mysql数据库操作模块
const multer = require('multer')//引入multer中间件处理文件
const upload = multer({ dest: 'public/uploads/' })//自动创建处理后的文件保存目录,同时可也可以指定拓展名


// 配置解析post参数的两个内置中间件
// 通过express.json()这个中间件,解析表单中的JSON格式的数据
app.use(express.json())//解析post的请求题参数(json格式)
// 通过express.urlencoded()这个中间件,来解析表单中的url-encoded格式的数据
app.use(express.urlencoded({extended:false}))//解析post的请求题参数(encoded格式)

//使用express.static()中间件来托管静态资源
app.use(express.static('./public'))

//upload.single():将前端form表单(指定name)传过来的文件数据传入到multer指定创建的文件夹中
app.post('/user',upload.single('headpic'), async (req,res)=>{
//输出即表示可以成功接收到数据,随后处理即可(存数据库还是怎样都行)
//multer中间件还为你的req中添加了一个file,里面以对象的形式存放着你传过来的文件数据
console.log(req.body,req.file);
// 对前端传过来的数据进行一个判断,到底有没有传文件过来(根据是否存在req.file来判断)
const headpic = req.file ? `/uploads/${req.file.filename}`:`/uploads/default.png`
/*
此时我们就可以将这个文件的路径名保存到数据库中,文件本身保存到服务器
后续我们想要删掉这些前端保存到服务端的文件仅需要引入fs模块进行操作即可
*/

// 存数据库将前端传过来的form表单数据存到数据库(用户名,文件路径)
var user = await promisePool.query(
`insert into user(username,headpic) values (?,?)`,
[req.body.username,headpic])//用户名和头像路径存到数据库

res.send({
msg:'文件成功存储到服务器并且将该文件的路径存到了数据库',
data:user[0]
})
})

app.get('/getuser',async (req,res)=>{
// 获取数据库中所有的用户信息(用户名,头像)
var user = await promisePool.query('select * from user')

res.send({
msg:'获取用户信息成功!',
data:user[0]//返回数据库中的数据
})
})



// 启动服务器
app.listen(3000,()=>{
console.log('服务器已启动! 端口3000正在监听...');
})


/* ------------------------- 数据库操作 ------------------------------ */
// 1.创建连接池,进行操作
const config = getConfig()//2.创建数据库连接对象
// 3.创建数据库连接池(promise形式调数据)
const promisePool = mysql.createPool(config).promise()

// 创建链接数据库函数
function getConfig(){
return {
host:'127.0.0.1',//域名
port: 3306,//端口号(mysql默认是3306)
user: 'root',//数据库的用户名
password: 'Zpl13189417387',//数据库的密码
database:'fileuploadnodejs',//要连接的数据库名称
connectionLimit:1//创建连接池的数量
}
}
  • 前端提交(文件上传)页面(upload.html)
<!DOCTYPE html>
<html lang="en">
<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">
<title>文件上传(前端form表单提交)</title>
</head>
<body>
<form action="/user" method="POST" enctype="multipart/form-data">
<div>
用户名:<input type="text" name="username">
</div>
<div>
头像:<input type="file" name="headpic">
</div>
<div>
<input type="submit" value="提交数据">
</div>
</form>
</body>
</html>
  • 前端文件展示页面(user.html)
<!DOCTYPE html>
<html lang="en">
<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">
<title>用户展示页</title>
<!-- 引入axios -->
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
</head>
<body>
<table border="2">
<thead>
<tr>用户名</tr>
<tr>头像</tr>
</thead>
<tbody>

</tbody>
</table>

<script>
// 获取展示列表
var tbody = document.querySelector('tbody')

// 页面一上来就获取数据库中的用户信息
axios.get('/getuser').then(res=>{
var data = res.data.data
console.log(res.data);
// alert(res.data.msg)

// 将获取到的数据填入到tbody中
tbody.innerHTML = data.map(item=>`
<tr>
<td>${item.username}</td>
<td><img src="${item.headpic}" /></td>
</tr>
`).join('')
})
</script>

<style>
img{
width: 50px;
height: 50px;
}
</style>
</body>
</html>

结果展示

  • 后端通过multer成功接收到前端传过来的multipart形式的数据
    image

  • 后端成功将文件(单张图片的存储路径)存到数据库
    image

  • 前端成功发送请求获取到数据库中的文件(单张图片)并展示到页面上
    image

真正意义上的前后端分离项目中

  • 前端通过发送ajax请求来获取到的文件数据(图片路径)只需要拼接上对应的服务器url(用axios的话就提前设置好baseUrl)即可
  • 前提是:后端要设置好跨域请求
    image