一.multer
官方介绍:
Multer 是一个 node.js 中间件,用于处理 multipart/form-data
类型的表单数据,它主要用于上传文件。它是写在 busboy 之上非常高效。
中文官方网址:
multer/README-zh-cn.md at master · expressjs/multer · GitHub
怎么使用就不介绍了,官方文档很详细
二、使用
1.单个文件(图片或视频都可以)上传
前端代码:
<input type="file" ref="file1" @change="fileChange1"/>
自己封装的向后端发送请求的函数:
// 导入自己封装的axios请求实例
import request from '../tools/request'
export const addArticle = data => {
return request({
method: 'post',
url: '/my/addActicle',
// url: '/my/addActicle2',
// url: '/my/addActicle3',
headers: {
'Content-Type': 'multipart/form-data'
},
data
})
}
vue代码:
<script>
//导入自己向后端发送请求的函数
import { addArticle } from '../../request/article'
export default {
data() {
return {
article: {
title: '文章标题',
cate_id: 1,
content: '这是文章内容测试',
state: '草稿'
}
}
},
methods: {
async fileChange1() {
//读取文件对象,并基于文件对象获取blob数据
const file = this.$refs.file1.files[0]
//为对象添加cover_img属性用来保存文件
this.article.cover_img = file
//向后端发送请求
await addArticle(this.article)
}
}
}
</script>
浏览器查看自己的发送参数:
后端路由代码:
const multer = require('multer')
//创建multer的实例对象,通过dest属性指定文件的存放路径
const upload = multer({ dest: path.join(__dirname, '../uploads') })
//'cover_img'为前端存储文件的属性名,必须一致
router.post('/addActicle', upload.single('cover_img'), addActicle)
自己封装的将后端接收到文件保存文件夹中:
//文章路由处理函数
const fs = require('fs')
const path = require('path')
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, `../upload/${imgName}`), data, err => {
//写入失败
if (err) { reject(err) }
//写入成功,同时返回需要存储在数据中的相对路径
resolve(`/upload/${imgName}`)
})
// 删除二进制文件
await fs.unlink(file.path, err => {
if (err) { reject(err) }
})
})
})
}
后端路由处理函数代码:
exports.addActicle = (req, res) => {
// console.log(req.body);//文本类型的数据
// console.log(req.file);//文件类型的数据
let file = req.file
console.log('通过multer解析文件信息对象', file);
saveImg(file, req.user.username).then(res => {
// res就是我返回的相对地址的位置
console.log(res);
}).catch(err => {
// 啊....啊 最苦恼的bug环节
console.log(err);
})
}
后端接收成功:
2.多个文件(图片或视频都可以)上传 (需要使用FormData来存储表单数据)
第一种方式
前端代码:
<input type="file" ref="file1" @change="fileChange1" multiple />
自己封装的向后端发送请求的函数:
// 导入自己封装的axios请求实例
import request from '../tools/request'
export const addArticle = data => {
return request({
method: 'post',
//url: '/my/addActicle',
url: '/my/addActicle2',
// url: '/my/addActicle3',
headers: {
'Content-Type': 'multipart/form-data'
},
data
})
}
vue代码:
<script>
import { addArticle } from '../../request/article'
export default {
data() {
return {
}
},
methods: {
async fileChange1() {
//读取文件对象,并基于文件对象获取blob数据
const files = this.$refs.file1.files
const form = new FormData()
for (const item of files) {
form.append('cover_img', item)
}
form.append('test', 1)
await addArticle(form)
}
}
}
</script>
浏览器查看自己的发送参数:
后端路由代码:
const multer = require('multer')
//创建multer的实例对象,通过dest属性指定文件的存放路径
const upload = multer({ dest: path.join(__dirname, '../uploads') })
//'cover_img'为前端存储文件的属性名,必须一致
router.post('/addActicle2', upload.array('cover_img', 3), addActicle2)
后端路由处理函数代码:
exports.addActicle2 = (req, res) => {
// console.log('通过token解析出来的用户信息对象', req.user);
console.log('通过multer解析表单的文本类型数据', req.body);
let files = req.files
console.log('通过multer解析表单的文件类型数据', files);
}
后端接收成功:
第二种方式
前端代码:
<input type="file" ref="file1" @change="fileChange1" multiple />
<input type="file" ref="file2" @change="fileChange2" multiple />
<button @click="addArticle">上传</button>
自己封装的向后端发送请求的函数:
// 导入自己封装的axios请求实例
import request from '../tools/request'
export const addArticle = data => {
return request({
method: 'post',
//url: '/my/addActicle',
//url: '/my/addActicle2',
url: '/my/addActicle3',
headers: {
'Content-Type': 'multipart/form-data'
},
data
})
}
vue代码:
<script>
import { addArticle } from '../../request/article'
export default {
data() {
return {
form: new FormData()
}
},
methods: {
async fileChange1() {
//读取文件对象,并基于文件对象获取blob数据
const file = this.$refs.file1.files[0]
this.form.append('cover_img', file)
this.form.append('test', 1)
},
async fileChange2() {
const file = this.$refs.file2.files[0]
this.form.append('avatar', file)
},
async addArticle() {
await addArticle(this.form)
}
}
}
</script>>
浏览器查看自己的发送参数:
后端路由代码:
const multer = require('multer')
//创建multer的实例对象,通过dest属性指定文件的存放路径
const upload = multer({ dest: path.join(__dirname, '../uploads') })
router.post('/addActicle3', upload.fields([{ name: 'cover_img', maxCount: 3 }, { name: 'avatar', maxCount: 2 }]), addActicle3)
后端路由处理函数代码:
exports.addActicle3 = (req, res) => {
console.log('通过token解析出来的用户信息对象', req.user);
console.log('通过multer解析表单的文本类型数据', req.body);
let files = req.files
console.log('通过multer解析表单的文件类型数据', files);
}
后端接收成功: