node.js使用multer实现单图、多图上传


前言

最近用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 => {
		// ┭┮﹏┭┮
	})
})

总结

写到这里就把常用操作介绍给了大家,可能其中有些错误我并没有发现,希望大家指正。

  • 3
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 8
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值