《家庭财务宝典》

使用 minio 部署自己的 oss 服务并搭配 nest 使用

20次阅读

共计 5368 个字符,预计需要花费 14 分钟才能阅读完成。

使用 minio 部署自己的 oss 服务并搭配 nest 使用插图

简述

本文主要是记录在搭建博客过程中,随着数据规模不断增长,存储和管理变得越来越重要。所以当时考虑使用图床或者 OSS 服务,于是买了一年的私人图床,因为价格便宜经常掉线,后面考虑更换 OSS 对象存储服务 。但是没钱,所以我考虑自己在服务区上部署一套 minio 对象存储服务 。下面是对 minio 的介绍以及这次部署的流程。

什么是 MinIO ?

根据官网的表述简单整理,MinIO 是一个开源的、轻量级、易于部署的对象存储服务器。它采用分布式架构,可以在多个节点上进行数据存储和访问,实现数据的冗余备份和高可用性。同时,它还具备强大的扩展性,可以根据需要进行水平扩展,以满足不断增长的存储需求。它可以用于构建私有云存储、备份存储、数据湖等各种场景。

MinIO 官网

环境准备

下载最新的稳定的 MinIO 二进制文件并将其安装到系统。

wget https://dl.min.io/server/minio/release/linux-amd64/minio
chmod +x minio
sudo mv minio /usr/local/bin/

启动服务

// 新建 monio 数据文件夹
mkdir -p /admin/minio/data /admin/minio/config

minio server /admin/minio/data --console-address :9999

启动成功后得到如下 log,证明 MinIO 启动成功。

使用 minio 部署自己的 oss 服务并搭配 nest 使用插图1

在浏览器中输入公网 ip + 端口 9999 能看到如下界面。

使用 minio 部署自己的 oss 服务并搭配 nest 使用插图2

配置 systemctl

MinIO 已经部署完成,接下来使用 systemctl 来管理 MinIO

使用 systemctl 管理 MinIO 有以下好处:

  1. 简化管理:systemctl 命令轻松地启动、停止、重启和重新加载 MinIO 服务,而无需手动操作
  2. 自动启动:通过将 MinIO 服务配置为自动启动,您可以确保在系统启动时自动启动 MinIO,无需手动干预。
  3. 状态监控:systemctl 提供了检查 MinIO 服务状态的命令,您可以随时查看服务是否正在运行以及其健康状态。
  4. 日志管理:systemctl 还提供了查看 MinIO 服务日志的命令,帮助您诊断和解决问题。

创建 systemd 服务单元文件

// 创建 minio.service 文件
touch /etc/systemd/system/minio.service

// 配置内容
vi /etc/systemd/system/minio.service

[Unit]
Description=MinIO Server // MinIO 服务的名称
Documentation=https://min.io/docs/minio/linux/index.html // 这个无所谓可以随便写,我写了 minio 文档的地址
After=network.target // 在网络连接完成后启动 MinIO 服务
 
[Service]
ExecStart=/root/minio server /admin/minio/data --console-address :9999 // 指定启动 MinIO 服务的命令行 /root/minio ==> minio 的安装位置 /admin/minio/data ==> minio 服务储存数据的目录 --console-address :9999 ==> 设置 minio 控制台的地址和端口
Restart=always // 如果服务意外停止,自动重新启动
Environment="MINIO_ROOT_USER=xxxxxx" "MINIO_ROOT_PASSWORD=xxxxxx" // 设置环境变量,用于指定 MinIO 的根用户和密码
 
[Install]
WantedBy=multi-user.target // 指定在多用户模式下启动 MinIO 服务 

启动 minio 服务

systemctl start minio
systemctl status minio

得到如下结果怎么 minio 服务启动完成

使用 minio 部署自己的 oss 服务并搭配 nest 使用插图3

新建 minio 访问密钥和储存桶

使用上面配置的账户密码进入 minio 管理界面,在下方 user 界面新建一个用户

使用 minio 部署自己的 oss 服务并搭配 nest 使用插图4

新增完成后点进去,在这边创建密钥

使用 minio 部署自己的 oss 服务并搭配 nest 使用插图5

在新建密钥界面就可以看到两个 key,一定要保存下来,这玩意只会出现一次

使用 minio 部署自己的 oss 服务并搭配 nest 使用插图6

完成密钥创建后再去 buckets 界面创建储存桶

使用 minio 部署自己的 oss 服务并搭配 nest 使用插图7

以上步骤完成后就可以在 nestjs 中使用 minio

nestjs 使用 minio 上传图片

MinIO JavaScript Client AP

安装官方提供的 minio javascript

npm install minio -S

全局配置文件加入 minio 配置 app.config.ts

export const minioConfig = {
  endPoint: 'xxx.xxx.xxx.xxx', // 服务器公网 ip
  port: 9000, // minio 挂载的端口,没指定的话一般是 9000
  useSSL: false, // 是否开启 SSL
  accessKey: 'xxxxxxxxxxxxxxx', // 访问密钥
  secretKey: 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', // 密钥
};

minio.service.ts 编写上传文件逻辑

import {Injectable} from '@nestjs/common';
import {HttpService} from '@nestjs/axios';
import * as Minio from 'minio';
import {v4} from 'uuid';
import * as dayjs from 'dayjs';

@Injectable()
export class MinIOService {
  private readonly minioClient: Minio.Client;
  constructor(private readonly httpService: HttpService) {this.minioClient = new Minio.Client(minioConfig);
  }
  // 多图片上传
  async uploadImageMultiple(file: Array<Express.Multer.File>) {let promiseList = [];
    const length = file.length; // 文件数量
    promiseList = file.map((item) => {return this.uploadImageWithMinio(item.originalname, item.buffer);
    });

    return Promise.all(promiseList).then((res) => {const status = res.map((item) => item.status); // 上传状态
      const trueCount = status.filter((item) => item === true).length; // 成功统计
      const falseCount = status.filter((item) => item === false).length; // 失败统计
      const links = [];
      const error = [];

      res.forEach((item) => {if (item.status) {links.push(item.data.links.url);
        } else {error.push(item);
        }
      });

      if (error.length> 0) {console.log('上传图片 Error', error);
      }

      const returnData = {msg: ` 共上传 ${length} 张图片,成功 ${trueCount},失败 ${falseCount}`,
        data: links,
      };

      return returnData;
    });
  }
  // 使用 minio 上传图片
  async uploadImageWithMinio(objectName: string, data: Buffer) {
    try {const fileExtension = objectName.match(/\.([^.]+)$/)[1]; // 获取文件后缀
      const newfilename = `${v4()}-${dayjs().format('YYYYMMDDHHmmss')}.${fileExtension}`; // 使用 uuid + 当前时间重写文件名
      await this.minioClient.putObject('blogpic', newfilename, data); // 调用 minio 提供的方法上传对象
      return {
        status: true,
        data: {
          links: {url: `https://dawdlepig.cn/blogpic/${newfilename}`, // 返回文件地址,这里我使用 nginx 做了代理,后面再说,一般文件地址是 ip + port+ bucketName + fileName
          },
        },
      };
    } catch (error) {console.log('oss 图片上传失败', error);
      return {
        status: false,
        error
      };
    }
  }
}

monio.controller.ts 组装接口

import {Controller, HttpException, HttpStatus, Post, UploadedFiles, UseInterceptors} from '@nestjs/common'
import {AnyFilesInterceptor} from '@nestjs/platform-express';
import {RequestResult} from 'src/common/interface/common.interface';
import {MinIOService} from './minio.service' 

@Controller('minio')
export class MinIOController {constructor(private readonly minioService: MinIOService) {}

  @Post('uploadImageOSS')
  @UseInterceptors(AnyFilesInterceptor())
  async uploadImageOSS(@UploadedFiles() files: Array<Express.Multer.File>,
  ): Promise<RequestResult> {if (!files || files.length === 0) {throw new HttpException('file 不能为空!', HttpStatus.OK);
    }
    const imageType = ['image/jpeg', 'image/png', 'image/gif', 'image/webp'];

    files.forEach((file) => {if (!imageType.includes(file.mimetype)) {throw new HttpException('文件类型错误', HttpStatus.OK);
      }
    });

    try {const res = await this.systemService.uploadImageMultiple(files, 'oss');

      return {
        data: res.data,
        msg: res.msg,
      };
    } catch (error) {console.error(error);
      throw new HttpException({ error, message: '图片上传失败'},
        HttpStatus.OK,
      );
    }
  }
}

自己按照 nest 文档写一下 module 就行

nginx 代理 minio

一般咱们发布网站都是有域名的,很少裸奔,所以我们的图片地址也需要使用 nginx 代理一下,下面是我的配置

location /blogpic/ {
  proxy_set_header X-Forwarded-Proto $scheme;
  proxy_set_header X-Real-IP $remote_addr;
  proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  proxy_set_header Host $http_host;
  proxy_connect_timeout 300;
  proxy_http_version 1.1;
  proxy_set_header Connection "";
  chunked_transfer_encoding off;
  proxy_pass http://localhost:9000;
}

可能遇到的错误

NoSuchkey ==> 检查自己的文件名是否正确

使用 minio 部署自己的 oss 服务并搭配 nest 使用插图8

AccessDenied ==> 检查 bucket 权限,是否设置成 Private 了,可以在 Buckets 界面更改,设置成 Public 或者自定义权限

使用 minio 部署自己的 oss 服务并搭配 nest 使用插图9

你的工作,由 AI 赋能!🔥

还在为文案、脚本卡壳、做视频、写代码、设计图片灵感枯竭而烦恼吗?🤯

板板 AI,你的工作好帮手!

一键生成    各种文案、脚本、图片、视频、代码、报告,轻松应对各种工作 / 营销需求!

现在注册体验,即可获得:

  • 🎁 30 积分基础模型余额
  • 🎁 3 积分高级模型余额
  • 🎁 3 积分绘画余额

还不快来试试?

点击链接,开启你的 AI 创作之旅!>>>https://www.banbanai.cn

板板 AI,让你的工作效果发挥无限可能! 🚀

正文完
关注板板AI免费获得移动AI助手
post-qrcode
 
天天
版权声明:本站原创文章,由 天天 2024-12-13发表,共计5368字。
转载说明:

本文由 天天资讯网 整理发布,转载请注明出处.
版权声明:部分文章内容或图片来源于网络,我们尊重作者的知识产权。如有侵犯,请联系我们在第一时间删除。

文字广告位10/月 文字广告位10/月 文字广告位10/月 文字广告位10/月 文字广告位10/月
文字广告位10/月 文字广告位10/月 文字广告位10/月 文字广告位10/月 文字广告位10/月
文字广告位10/月 文字广告位10/月 文字广告位10/月 文字广告位10/月 文字广告位10/月
文字广告位10/月 文字广告位10/月 文字广告位10/月 文字广告位10/月 文字广告位10/月
文字广告位10/月 文字广告位10/月 文字广告位10/月 文字广告位10/月 文字广告位10/月

温馨提示:请在上面搜索| 查找更多免费资源,如需广告位请联系站长QQ 48704478

《家庭财务宝典》