文章开始之前分享两个开源项目,会一直维护的,欢迎 star,如果你感兴趣或者想参与学习,可以加我微信 yunmz777,最近也在找工作 ing,欢迎内推......
浪费你两秒钟时间,我们正文开始!!!
最近在做毕业项目,而且毕业项目用的是公司的项目,因为已经离职了,而且公司的 oss 服务也到期了,所以就导致了之前写的一些东西无法运行,但是又不想花太多时间去配置一些阿里云 oss 的服务之类的,于是便使用 minio 自己搭了一个。
这篇文章中我们已经讲解到了如何使用 docker-compose 来搭建一个 minio 服务了,如果不懂的话可以到这里进行阅读:
接下来的内容中我们将讲解如何在 nestjs 中集成 minio 服务。
配置 minio
首先我们先配置一下我们的基本服务,因为我们设置了环境变量,那么我们可以把我们的账号和密码配置在环境变量上面:
MINIO_ENDPOINT= localhost
MINIO_PORT= 9000
MINIO_ACCESS_KEY= moment
MINIO_SECRET_KEY= moment666
环境变量配置完成之后,我们配置一个 ts 枚举类型来:
export enum MiNiOConfigEnum {
MINIO_ENDPOINT = "MINIO_ENDPOINT",
MINIO_PORT = "MINIO_PORT",
MINIO_ACCESS_KEY = "MINIO_ACCESS_KEY",
MINIO_SECRET_KEY = "MINIO_SECRET_KEY",
}
在上面键和值都是相同的,这样就能对应到我们环境变量中设置的值了,这个时候我们就可以添加我们的 minio 配置了:
import { ConfigService } from "@nestjs/config";
import { MiNiOConfigEnum } from "@/common/enum/config.enum";
interface MiNiOConfig {
endPoint: string;
port: number;
useSSL: boolean;
accessKey: string;
secretKey: string;
}
export default function loadMiNiOConfig(
configService: ConfigService
): MiNiOConfig {
const { MINIO_ACCESS_KEY, MINIO_ENDPOINT, MINIO_PORT, MINIO_SECRET_KEY } =
MiNiOConfigEnum;
return {
endPoint: configService.get(MINIO_ENDPOINT),
port: parseInt(configService.get(MINIO_PORT), 10),
useSSL: false,
accessKey: configService.get(MINIO_ACCESS_KEY),
secretKey: configService.get(MINIO_SECRET_KEY),
};
}
这里返回了一个对象,这里都是我们连接 minio 要用到的参数。
配置一个 minio 通用服务
首先我们要创建一个通用服务,让他可以在我们需要用到的地方都可以使用到,而不是写死,并且这个文件模块也可以直接迁移到其他项目里去:
在开始之前,我们需要安装一下 minio:
pnpm add minio
安装完成之后,我们编写如下代码:
// src/minio/minio.module.ts
import { Global, Module } from "@nestjs/common";
import * as Minio from "minio";
import { ConfigService } from "@nestjs/config";
import { MinioService } from "./minio.service";
import loadMiNiOConfig from "@/config/minio.config";
@Global()
@Module({
providers: [
{
provide: "MINIO_CLIENT",
useFactory: async (configService: ConfigService) => {
const minioConfig = loadMiNiOConfig(configService);
const minioClient = new Minio.Client(minioConfig);
return minioClient;
},
inject: [ConfigService],
},
MinioService,
],
exports: [MinioService],
})
export class MinioModule {}
模块编写完成之后,我们要编写我们的服务了:
import { Inject, Injectable } from "@nestjs/common";
import * as Minio from "minio";
import { MulterFile } from "@webundsoehne/nest-fastify-file-upload";
@Injectable()
export class MinioService {
constructor(
@Inject("MINIO_CLIENT") private readonly minioClient: Minio.Client
) {}
async getBuckets() {
return await this.minioClient.listBuckets();
}
async uploadFile(bucketName: string, fileName: string, file: MulterFile) {
await this.minioClient.putObject(bucketName, fileName, file.buffer);
const expiry = 24 * 60 * 60;
const presignedUrl = await this.minioClient.presignedUrl(
"GET",
bucketName,
fileName,
expiry
);
return {
url: presignedUrl,
};
}
async presignedPutUrl(
bucketName: string,
fileName: string,
expiry: number = 24 * 60 * 60
) {
return await this.minioClient.presignedPutObject(
bucketName,
fileName,
expiry
);
}
async presignedGetUrl(
bucketName: string,
fileName: string,
expiry: number = 24 * 60 * 60
) {
return await this.minioClient.presignedGetObject(
bucketName,
fileName,
expiry
);
}
async presignedPostPolicy(
bucketName: string,
fileName: string,
expiry: number = 24 * 60 * 60
) {
const policy = new Minio.PostPolicy();
policy.setBucket(bucketName);
policy.setKey(fileName);
policy.setExpires(new Date(new Date().getTime() + expiry * 1000));
return await this.minioClient.presignedPostPolicy(policy);
}
}
在上面的这些代码中我们在构造函数 中通过 @Inject('MINIO_CLIENT') 装饰器注入了一个 MinIO 的客户端实例。这允许服务中的各方法使用这个客户端与 MinIO 服务进行交互。
并且编写了一些方法来对 minio 进行了一些基本的封装:
getBuckets():使用 MinIO 客户端的 listBuckets() 方法来获取所有的存储桶(buckets)。这是一个异步操作,返回一个包含所有存储桶信息的列表。
uploadFile(bucketName, fileName, file):将文件上传到指定的存储桶和文件名。这里 file.buffer 包含了文件的数据。
presignedPutUrl(bucketName, fileName, expiry):生成一个预签名的 PUT URL,允许用户在指定的时间(默认 24 小时)内上传文件到指定的存储桶和文件名位置。
presignedGetUrl(bucketName, fileName, expiry):生成一个预签名的 GET URL,允许用户在指定的时间(默认 24 小时)内从指定的存储桶下载文件。
presignedPostPolicy(bucketName, fileName, expiry):创建一个预签名的 POST 策略。这个策略定义了通过 HTTP POST 方法上传文件的规则。
接下来我们将用 nestjs 编写一个简单的接口来测试一下我们所封装的服务。
在这里我们编写了一个简单的服务,用来获取文件上传的签名,并且为了方便,我们固定了上传之后的文件名为 077.webp:
访问该接口返回如下数据:
之后我们使用这个返回的 url 来发起一个 put 请求:
返回这样的数据则表示我们的文件成功上传到 minio 服务了:
上传成功了,预览也成功预览了:
点击 share 我们就可以把链接分享给其他小伙伴了,但是现在这是一个本地的服务,暂时还不能分享,得部署上线才可以。
总结
通过上面的内容中我们通过 nestjs 结合 minio 实现了一个图床的服务,这样我们就可以抛弃阿里云的 oss 服务了。