使用 multer 在 node.js 上实现单图像、多图像上传
最编程
2024-07-18 17:04:19
...
文章目录
- 前言
- 一、multer是什么?
- 二、使用步骤
- 1.下载
- 2.引入
- 3.单图上传
- 4.多图上传
- 1.第一种方法:
- 2、第二种方法
- 5.保存图片
- 总结
前言
最近用node.js搞项目,其中用到了multer
进行图片上传,中途遇到了一些问题,这里将一些常用操作和问题进行汇总。
一、multer是什么?
multer是一个能更好的处理node.js服务器接收的文件上传的中间件,蛮好用的。其中文文档链接如下:
multer中文文档https://github.com/expressjs/multer/blob/master/doc/README-zh-cn.md
二、使用步骤
1.下载
在项目根目录下使用如下命令:
npm i multer
2.引入
在要使用的地方引入,代码如下:
var multer = require('multer')
// 这里是最简单的配置,指明二进制文件保存保存至根目录下的xxx文件夹内
// 我这里保存在自己创建的uploads文件夹内
var upload = multer({ dest: 'uploads/' })
3.单图上传
node.js新增一个接口,代码如下:
// 这里的upload就是上文的multer的配置对象
// 这里的single中的字符串要对应上传input的name
// 或者是对应formdata的键名
router.post('/uploadAvatar', upload.single('avatar'), (req, res) => {
// 这里获取到的就是前端上传的文件
let file = req.file
// 图片文件的保存操作将在下面写出
})
前端示例使用from表单进行上传(最方便了,才不是因为我懒,嘿嘿嘿),代码如下:
<form action="xxx/upload/uploadAvatar" method="post" enctype="multipart/form-data">
<h3>单图上传</h3>
<input type="file" name="avatar">
<input type="submit" value="提交">
</form>
在开启服务、前端上传图片后,在控制台可以输出得到的file:
// 各种属性一目了然
{
fieldname: 'avatar',
originalname: 'avatar.png',
encoding: '7bit',
mimetype: 'image/png',
destination: 'uploads/',
filename: '83ba46c879c168c2f25fab16d32b8287',
path: 'uploads\\83ba46c879c168c2f25fab16d32b8287',
size: 4649268
}
4.多图上传
1.第一种方法:
node.js新增一个接口,将upload.single('xxx)
替换成upload.array('xxx', 上传数量)
,需要注意的是,这样做可能会导致移动端上传只要一张图片。
// 多图上传要将upload.single 替换成 upload.array
// 这里的papers跟上文的avatar都需要前后端对应
// 2 是我限制的上传数量,可以自己定义
router.post('/uploadPapers', upload.array('papers', 2), (req, res) => {
// 获取到前端上传文件列表
// 这里需要注意的是多文件上传,文件是保存在req(request)的files属性内
let files = req.files
})
前端部分如下:
<form action="xxx/upload/uploadPapers" method="post" enctype="multipart/form-data">
<h3>多图上传</h3>
<input type="file" name="papers">
<input type="file" name="papers">
<input type="submit" value="提交">
</form>
在控制台输出可以得到文件数组,这里就不加以赘述。
2、第二种方法
// 这里将upload.array 替换成 upload.fields
// 这里的name要跟前端对应
// maxCount 是限制的上传数量,可以自己定义
router.post('/uploadPapers', upload.fields([{ name: 'card', maxCount: 1 }, { name: 'user', maxCount: 1 }]), (req, res) => {
// 获取到前端上传文件列表
// 这里需要注意的是多文件上传,文件是保存在req(request)的files属性内
// 但是需要注意的是,这里的files获取到的是两个name对应的文件数组,需要将文件提取出来
// xxx
})
5.保存图片
我将其封装成了一个函数,如下:
// 用到了如下模块
// 在头部引入即可
const fs = require('fs')
const path = require('path')
// file 图片文件
// sign 标识(用户唯一id、其他唯一值皆可)
function saveImg(file, sign) {
return new Promise((resolve, reject) => {
fs.readFile(file.path, async (err, data) => {
if (err) {
reject(err)
}
// 拓展名
let extName = file.mimetype.split('/')[1]
// 拼接成图片名
// 这里可以自行修改
let imgName = `${sign}-${Date.now()}.${extName}`
// 写入图片
// 写入自己想要存入的地址
await fs.writeFile(path.join( __dirname, `xxx/${imgName}`), data, err => {
if (err) { reject(err) }
})
// 删除二进制文件
await fs.unlink(file.path, err => {
if (err) { reject(err) }
})
// 验证是否存入
await fs.stat(path.join( __dirname, `xxx/${imgName}`), err => {
if (err) { reject(err) }
// 成功就返回图片相对地址
resolve(`xxx\\${imgName}`)
})
})
})
}
// 使用实例
// 单图保存
router.post('/uploadAvatar', upload.single('avatar'), (req, res) => {
let file = req.file
saveImg(file).then(res => {
// res就是我返回的相对地址的位置
}).catch(err => {
// 啊....啊 最苦恼的bug环节
})
})
// 多图保存
router.post('/uploadPapers', upload.array('papers', 2), (req, res) => {
let files = req.files
Promise.all(
files.map( async file => await saveImg(file))
).then([...list] => {
// list保存了所有文件地址返回的相对地址
// 可以进行相应的操作
}).catch(err => {
// ┭┮﹏┭┮
})
})
总结
写到这里就把常用操作介绍给了大家,可能其中有些错误我并没有发现,希望大家指正。