插件:egg-oss
安装:npm i egg-oss --save
文档:https://www.npmjs.com/package/egg-oss
配置:config/plugin.js
oss: {
enable: true,
package: 'egg-oss',
}
配置:config/config.default.js
config.oss = {
client: {
accessKeyId: 'LTAI4DS1yG3E9z3dGijcqEvv',
accessKeySecret: 'cwFVsXF5S5n75a8NZIz0IS2EO5pqvl',
bucket: 'demo-mp3',
endpoint: 'oss-cn-shenzhen.aliyuncs.com',
timeout: '60s',
},
};
// 上传格式和大小限制
config.multipart = {
// fileSize: '50mb',
fileSize: 1048576000,
// mode: 'stream',
mode: "file",
fileExtensions: [
// images
'.jpg', '.jpeg', // image/jpeg
'.png', // image/png, image/x-png
'.gif', // image/gif
'.bmp', // image/bmp
'.wbmp', // image/vnd.wap.wbmp
'.webp',
'.tif',
'.psd',
// text
'.svg',
'.js', '.jsx',
'.json',
'.css', '.less',
'.html', '.htm',
'.xml',
// tar
'.zip',
'.gz', '.tgz', '.gzip',
// video
'.mp3',
'.mp4',
'.avi',
],
};
创建数据迁移表
npx sequelize migration:generate --name=file
1.执行完命令后,会在database / migrations / 目录下生成数据表迁移文件,然后定义
'use strict';
module.exports = {
up: (queryInterface, Sequelize) => {
const { INTEGER, STRING, DATE, ENUM, TEXT } = Sequelize;
return queryInterface.createTable('file', {
id: {
type: INTEGER(20),
primaryKey: true,
autoIncrement: true
},
name: {
type: STRING(100),
allowNull: false,
defaultValue: '',
comment: '文件名'
},
ext: {
type: STRING(50),
allowNull: true,
defaultValue: '',
comment: '文件扩展名'
},
md: {
type: STRING,
allowNull: true,
defaultValue: '',
comment: '文件MD5'
},
file_id: {
type: INTEGER,
allowNull: false,
defaultValue: 0,
comment: '父级id'
},
user_id: {
type: INTEGER,
allowNull: false,
defaultValue: 0,
comment: '用户id',
references: {
model: 'user',
key: 'id'
},
onDelete: 'cascade',
onUpdate: 'restrict', // 更新时操作
},
size: {
type: INTEGER,
allowNull: false,
defaultValue: 0,
comment: '文件大小'
},
url: {
type: STRING,
allowNull: true,
defaultValue: '',
comment: '图片真实url'
},
isdir: {
type: INTEGER,
allowNull: false,
defaultValue: 0,
comment: '是否为文件夹',
},
created_time: DATE,
updated_time: DATE,
});
},
down: (queryInterface, Sequelize) => {
return queryInterface.dropTable('file');
}
};
- 执行 migrate 进行数据库变更
npx sequelize db:migrate
模型创建
// app/model/file.js
module.exports = app => {
const { STRING, INTEGER, DATE, ENUM, TEXT } = app.Sequelize;
const File = app.model.define('file', {
id: {
type: INTEGER(20),
primaryKey: true,
autoIncrement: true
},
name: {
type: STRING(100),
allowNull: false,
defaultValue: '',
comment: '文件名'
},
ext: {
type: STRING(50),
allowNull: true,
defaultValue: '',
comment: '文件扩展名'
},
md: {
type: STRING,
allowNull: true,
defaultValue: '',
comment: '文件MD5'
},
file_id: {
type: INTEGER,
allowNull: false,
defaultValue: 0,
comment: '父级id'
},
user_id: {
type: INTEGER,
allowNull: false,
defaultValue: 0,
comment: '用户id',
references: {
model: 'user',
key: 'id'
},
onDelete: 'cascade',
onUpdate: 'restrict', // 更新时操作
},
size: {
type: INTEGER,
allowNull: false,
defaultValue: 0,
comment: '文件大小'
},
url: {
type: STRING,
allowNull: true,
defaultValue: '',
comment: '图片真实url'
},
isdir: {
type: INTEGER,
allowNull: false,
defaultValue: 0,
comment: '是否为文件夹',
},
created_time: DATE,
updated_time: DATE,
});
// 删除后
File.afterBulkDestroy(async (data, option) => {
console.log('删除后', data.where);
let files = await app.model.File.findAll({
where: {
file_id: data.where.id,
user_id: data.where.user_id,
isdir: 1
}
});
let ids = files.map(item => item.id);
if (ids.length > 0) {
app.model.File.destroy({
where: {
id: ids,
user_id: data.where.user_id
}
});
}
});
return File;
};
控制器:app/controller/file.js
// 引入
const fs = require('fs');
const path = require('path');
// 上传
async upload() {
const { ctx, app } = this;
const currentUser = ctx.authUser;
if (!ctx.request.files) {
return ctx.apiFail('请先选择上传文件');
}
ctx.validate({
file_id: {
type: "int",
required: true,
defValue: 0,
desc: 'file_id'
},
});
const file_id = ctx.query.file_id;
// 文件id是否存在
if (file_id > 0) {
// 目录是否存在
await this.service.file.isDirExist(file_id);
}
const file = ctx.request.files[0];
const name = 'egg-oss-demo/' + ctx.genID(10) + path.extname(file.filename);
// 验证用户剩余内存是否满足要求
let s = await (new Promise((resolve, reject) => {
fs.stat(file.filepath, (err, stats) => {
resolve((stats.size / 1024).toFixed(1));
});
}));
if ((currentUser.total_size - currentUser.used_size) < s) {
return ctx.apiFail('你的可用内存不足');
}
let result;
try {
result = await ctx.oss.put(name, file.filepath);
} catch (err) {
console.log(err);
}
if (result) {
// 写入数据表
let addData = {
name: file.filename,
ext: file.mimeType,
md: result.name,
file_id,
user_id: currentUser.id,
size: parseInt(s),
isdir: 0,
url: result.url
};
if (file_id > 0) {
addData.file_id = file_id;
}
let res = await app.model.File.create(addData);
// 更新user表的使用内存
currentUser.used_size = currentUser.used_size + parseInt(s);
currentUser.save();
return ctx.apiSuccess(res);
}
ctx.apiFail('上传失败');
}
服务:app/service/file.js
// 目录是否存在
async isDirExist(id) {
let f = await this.app.model.File.findOne({
where: {
id,
// 当前用户id
user_id: this.ctx.authUser.id,
isdir: 1
}
});
if (!f) {
return this.ctx.throw(404, '目录不存在');
}
return f
}
扩展:app/extend/context.js
// 生成唯一id
genID(length) {
return Number(Math.random().toString().substr(3, length) + Date.now()).toString(36);
}
路由:app/router.js
router.post('/upload', controller.file.upload);
喜欢本章文章的,麻烦给个关注和点赞,你的一个小小的点赞,是作者无限进步的动力!!
微信公众号,更多资源等你来!!