一、使用 http-errors 处理状态码
npm i http-errors
const createError = require('http-errors')
function failure(res, error) {
let statusCode = 500
let errors = '服务器错误'
if(error.name === 'SequelizeValidationError') { // Sequelize 验证错误
statusCode = 400
errors = error.errors.map(err => err.message)
} else if(error.name === 'JsonWebTokenError' || error.name === 'TokenExpiredError') { // Token验证错误
statusCode = 401
errors = 'Token验证失败'
} else if(error instanceof createError.HttpError) { // http-errors 库创建的错误
statusCode = error.status
errors = error.message
}
res.status(statusCode).json({
status:false,
message: `请求失败:${error.name}`,
errors: Array.isArray(errors) ? errors : [errors]
})
}
二、使用Multer上传图片到阿里云 OSS(对象存储)
# 对象存储OSS -> Bucket列表 -> 创建Bucket
# Bucket名称:
# 地域:
# 阻止公共访问:关闭
# 读写权限:公众读
# 完成创建
# 直接使用阿里云网站上传
## 进入Bucket -> 上传文件 -> 选择文件 -> 点击上传
# 开发上传接口
# 服务端代理上传
## 客户端 - 上传文件 -> 业务服务器 - 上传文件 -> 对象存储
## 缺点:一张图片先上传到Node服务器上,再上传到阿里云OSS。这张图片上传两次,造成资源的浪费
## 优点:前端开发简单,后端也可以很方便的记录
# 客户端直传
## 客户端 - 获取授权 -> 业务服务器
## 客户端 - 上传文件 -> 对象存储
## 优点:图片不用经过客户端的中转,服务器开销非常小,上传速度也会快很多
## 缺点:开发上代码麻烦点,使用上前端需要调用两次接口
# 点击阿里云头像 -> AccessKey管理 -> 开始使用子用户AccessKey -> 创建用户
# OpenAPI调用访问 勾选 -> 确定 -> 手机号验证
# 选择用户 -> 添加权限 -> AliyunOSSFullAccess -> 确认新增授权
# 用户信息: AccessKey ID 和 AccessKey Secret
# node项目 .env文件增加配置
ALIYUN_ACCESS_KEY_ID= # AccessKey ID
ALIYUN_ACCESS_KEY_SECRET= # AccessKey Secret
ALIYUN_BUCKET= # 阿里云OSS -> 概览 -> 基本信息 -> 存储空间名称
ALIYUN_REGION= #阿里云OSS -> 概览 -> 访问端口 -> 地域节点 -> 小数点前面的部分
# 安装上传需要的依赖包
npm i ali-oss multer multer-aliyun-oss
# ali-oss 是用来操作阿里云OSS的SDK
# multer 上传文件的node.js中间件
# multer-aliyun-oss 是配置multer将文件上传到阿里云OSS
# 阿里云OSS -> 跨域设置 -> 创建规则
# 来源:*
# 允许Methods:POST
# 允许Headers:*
# 确认
const multer = require('multer')
const multerAliyunOss = require('multer-aliyun-oss')
const OSS = require('ali-oss')
// 阿里云配置信息
const config = {
accessKeyId: process.env.ALIYUN_ACCESS_KEY_ID,
accessKeySecret: process.env.ALIYUN_ACCESS_KEY_SECRET,
bucket: process.env.ALIYUN_OSS_BUCKET,
region: process.env.ALIYUN_OSS_REGION,
}
const client = new OSS(config)
// multer 配置信息
const upload = multer({
storage: multerAliyunOss({
config: config,
destination: 'uploads', // 自定义上传目录
}),
limits: {
fileSize: 1024 * 1024 * 5, // 限制文件大小为 5MB
},
fileFilter: (req, file, cb) => {
// 限制文件类型为图片
if (!file.originalname.match(/\.(jpg|jpeg|png|gif)$/)) {
return cb(new Error('只支持上传图片文件'))
}
cb(null, true)
},
})
// 单文件上传,指定表单字段名为 file
const singleUpload = upload.single('file')
module.exports = {
config,
client,
singleUpload,
}
1. 服务端代理上传
const express = require('express')
const router = express.Router()
const { success, failure } = require('../utils/responses')
const { singleUpload } = require('../utils/aliyun')
/**
* 阿里云 OSS 上传文件
* @route POST /uploads/aliyun
*/
router.post('/aliyun', singleUpload, (req, res) => {
try {
singleUpload(req, res, (err) => {
if (err) {
return failure(res, err)
}
if(!req.file) {
return failure(res, new Error('文件上传失败'))
}
success(res, '上传成功', {
file: req.file
})
})
} catch (error) {
failure(res, error)
}
})
module.exports = router
2、客户端直传
npm install uuid
const express = require('express')
const router = express.Router()
const { success } = require('../utils/responses')
const { client, config } = require('../utils/aliyun')
const {v4: uuidv4} = require('uuid')
const moment = require('moment')
/**
* 获取直传阿里云 OSS授权信息
* Get /uploads/aliyun/authorize
*/
router.get('/aliyun/authorize', async(req, res) => {
// 有效期
const date = moment().add(1, 'day')
// 自定义上传目录和文件名
const key = `uploads/${uuidv4()}`
// 上传安全策略
const policy = {
expiration: date.toISOString(),
conditions: [
['content-length-range', 0, 1024 * 1024 * 5], // 限制文件大小为 5MB
{bucket: client.options.bucket}, // 限制上传的 bucket
['eq', '$key', key], // 限制文件名
['eq', '$Content-Type', ['image/jpeg', 'image/png', 'image/gif', 'image/webp']], // 限制文件类型
],
}
// 签名
const formData = await client.calculatePostSignature(policy)
// bucket 域名 阿里云上传地址
const host = `https://${config.bucket}.${await client.getBucketLocation().location}.aliyuncs.com`.toString()
// 返回参数
const params = {
expires: date.format('YYYY-MM-DD HH:mm:ss'),
policy: formData.policy,
signature: formData.signature,
accessid: formData.OSSAccessKeyId,
host,
key,
url: `${host}/${key}`,
}
success(res, '获取阿里云授权信息', params)
})
module.exports = router
三、自动备份数据库到阿里云OSS
# 宝塔 -> 软件商店 -> 阿里云OSS -> 安装 -> 设置
# 填入阿里云OSS相关数据
# 保存路径:/backup
# 确认
# 宝塔 -> 计划任务 -> 添加任务
# 任务类型:备份数据库
# 执行周期:每天 4:30
# 数据库 备份到阿里云OSS 保留最新3份
# 同时保留本地备份
# 确定