实现
第一步,引入依赖
const fs = require('fs')
const multer = require('multer')
第二步,先设置一个上传守卫,用于初步拦截异常请求
/**
* 上传守卫
* @param req
* @param res
* @param next
*/
function uploadFile (req, res, next) {
// dest 值为文件存储的路径;single方法,表示上传单个文件,参数为表单数据对应的key
let upload = multer({dest: 'uploads/'}).single('file')
upload(req, res, (err) => {
// 获取文件相应数据
let file = req.file
let menutype = req.body.type
// 判断是否有上传文件
if (file !== undefined) {
const isJPG = file.mimetype !== undefined ? file.mimetype === 'image/jpeg' | file.mimetype === 'image/png' : false
const isLt2M = file.size !== undefined ? file.size / 1024 / 1024 < 2 : false
const filepath = file.filename !== undefined ? './uploads/' + file.filename : ''
const fileName = file.originalname !== undefined ? file.originalname : ''
// 判断文件处理是否异常
if (err) {
// 删除临时文件
fs.unlinkSync(filepath)
user.uploadLog(req, fileName, 'false', '文件类型或大小异常错误,请按提示选择文件', 'upload', err)
res.end(JSON.stringify({
traceId: req.traceId,
code: 301,
msg: '文件类型或大小异常错误,请按提示选择文件',
data: err
}))
} else if (!isJPG | !isLt2M) {
// 删除临时文件
fs.unlinkSync(filepath)
user.uploadLog(req, fileName, 'false', '文件类型或大小超过限制,请按提示选择文件', 'upload', '')
res.end(JSON.stringify({
traceId: req.traceId,
code: 302,
msg: '文件类型或大小超过限制,请按提示选择文件',
data: 'isJPG:' + isJPG + ';isLt2M:' + isLt2M
}))
} else if (uploadtype.indexOf(menutype) === -1) {
// 删除临时文件
fs.unlinkSync(filepath)
user.uploadLog(req, '', 'false', '上传类型不能为空或者其他', 'upload', '')
res.end(JSON.stringify({
traceId: req.traceId,
code: 308,
msg: '请求参数缺失或不正确',
data: 'type类型不合法'
}))
} else {
// 执行上传操作
next()
}
}
})
}
第三步,写接口,并引用上面的上传守卫
/**
* 后端upload上传文件到本地
* file 上传的文件
* type 上传类型(头像/聊天)
*/
router.post('/upload', uploadFile, (req, res) => {
let file = req.file
let menutype = req.body.type
// 获取文件后缀名,如'.jpg'
let index = file.originalname.lastIndexOf('.')
let type = file.originalname.substr(index)
// 获取当前年月,作为区分子目录
let month = moment(Date.now()).format('YYYY-MM')
// 随机生成16进制的28位数的文件名,用于上传oss时显示
let ossName = Math.random().toString(16).slice(2) + Math.random().toString(16).slice(2)
ossName = `${ossName}${type}`
// 拼接新文件存储路径(文件目录+随机数+文件后缀名),用于上传oss时显示
let osspath = ''
if (menutype === 'avatar') {
osspath = 'upload/' + month + '/' + ossName
} else {
osspath = 'chart_upload/' + month + '/' + ossName
}
// 临时文件在服务器中的本地路径
let filePath = './' + req.file.path
// 重写文件,生成图片,用于上传
fs.rename(filePath, ossName, (err) => {
if (err) {
res.end(JSON.stringify({
traceId: req.traceId,
code: 306,
msg: '临时文件重写为图片失败',
data: err
}))
} else {
// 复制文件到指定目录
fs.cp(ossName, 'uploads/' + osspath, (err) => {
// 删除原文件
fs.unlink(ossName, err => {
if (err) {
console.log('自动删除上传的源文件失败:' + err)
} else {
}
})
if (err) {
res.end(JSON.stringify({
traceId: req.traceId,
code: 307,
msg: '图片移动到指定文件夹失败',
data: err
}))
} else {
res.end(JSON.stringify({
traceId: req.traceId,
code: 200,
msg: '文件上传成功',
data: osspath
}))
}
})
}
})
})