Nodejs 文件上传minio
依赖
"dependencies": {
"express": "^4.18.2",
"multer": "^1.4.2",
"minio": "^7.0.32",
}
$ node -v
v18.14.2
minio.js
const Minio = require("minio");
const createMinioClient = () => {
return new Minio.Client({
endPoint: 'localhost',
port: 9000,
useSSL: false,
accessKey: 'HVETHsd1EfWFSA7m',
secretKey: 'pmo0HUIzfNJyCHULcmxEgIC1ls3YuJcu'
});
}
module.exports = {
createMinioClient
}
File.js
const {Sequelize} = require('sequelize');
const sequelize = require('./sequelize');
// 测试连接
(async () => {
try {
await sequelize.authenticate();
console.log('Connection has been established successfully.');
} catch (error) {
console.error('Unable to connect to the database:', error);
}
})();
const File = sequelize.define('file', {
id: {
type: Sequelize.INTEGER,
autoIncrement: true,
primaryKey: true,
},
name: {
type: Sequelize.STRING,
allowNull: false,
},
size: {
type: Sequelize.INTEGER,
allowNull: false,
},
type: {
type: Sequelize.STRING,
allowNull: false,
},
bucket: {
type: Sequelize.STRING,
allowNull: false,
},
objectName: {
type: Sequelize.STRING,
allowNull: false,
},
etag: {
type: Sequelize.STRING,
allowNull: false,
}
});
(async () => {
try {
// 检查当前数据库状态并根据模型定义自动更新表结构 例如,要强制执行同步并输出日志
await sequelize.sync({ force: true, logging: console.log });
console.log('All models were synchronized successfully.');
} catch (error) {
console.error('An error occurred while synchronizing the models:', error);
}
})();
module.exports = File;
Sequelize的 sync 方法的 SyncOptions 可选参数如下:
- force: 如果为 true,则会在执行同步之前删除表(如果已存在),并重新创建它。默认为 false。如果要在生产环境中使用 force: true,需要非常小心,因为它会删除所有表的数据。一般情况下,只在开发阶段使用。
- match: 只同步符合指定正则表达式的表。
- logging: 定义是否输出日志信息。可以是一个布尔值,表示是否在控制台输出日志,也可以是一个函数,接收日志信息作为参数,并将其发送到日志存储位置。默认为 console.log。
- alter: 如果设置为 true,则 Sequelize 将尝试根据模型定义来更新表。只会改变表格中的属性,不会删除或修改当前行。如果新的属性没有默认值,Sequelize 将执行 ALTER TABLE 来将其添加到表中。如果默认值已存在,则不会尝试更改表中的数据。请注意,alter 选项不能与 force 选项一起使用。
- hooks: 如果设置为 true,则 Sequelize 将在每个模型的 beforeSync 和 afterSync 钩子之间运行所有钩子。默认为 true。也可以指定要在 beforeSync 或 afterSync 钩子中运行的模型的列表。
这些选项可用于配置同步操作。例如,要强制执行同步并输出日志,可以使用以下代码:
const express = require('express');
const multer = require('multer');
const { PassThrough } = require('stream')
const { createMinioClient } = require('./minio');
const util = require("util");
const File = require('./File');
const app = express();
// 配置Multer
const storage = multer.memoryStorage();
const upload = multer({storage: storage});
const minioClient = createMinioClient();
let bucket = 'image';
const uploadFile = async (req, res) => {
try {
const { originalname, size, mimetype, buffer } = req.file;
const bufferStream = new PassThrough()
bufferStream.end(buffer)
console.log(util.inspect(req.file, true));
// 上传文件到 Minio
const result = await new Promise((resolve, reject) => {
minioClient.putObject(bucket, originalname, bufferStream, buffer.length, function(err, etag) {
if (err) return reject(err)
console.log('File.js uploaded successfully. etag:',etag.etag)
resolve(etag)
})
})
// 根据 etag 去重
const existingFile = await File.findOne({
where: {
etag:result.etag,
},
});
if (existingFile) {
// 如果已经存在相同 etag 的文件,则不需要重复上传,直接返回已有的文件信息
console.log(`File with etag ${result.etag} already exists, returning existing file information`);
return res.send(existingFile);
}
// 将上传文件的相关信息保存到数据库中
const file = await File.create({
name: originalname,
size,
type: mimetype,
bucket,
objectName: originalname,
etag: result.etag,
});
console.log(`File information saved to database: ${JSON.stringify(file)}`);
res.send(file);
} catch (err) {
console.error(err);
res.status(500).send('Upload failed');
}
};
app.get('/upload',async function (req, res) {
const existingFile = await File.findAll();
return res.send(existingFile);
});
// 处理文件上传请求
app.post('/upload', upload.single('file'), uploadFile);
// 处理其他中间件
// 启动应用程序
app.listen(3000, () => {
console.log('App started on port 3000');
});