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');
});