MinIO - is a cloud-native object store built to run on any infrastructure - public, private or edge clouds. Primary use cases include data lakes, databases, AI/ML, SaaS applications and fast backup & recovery. MinIO is dual licensed under GNU AGPL v3 and commercial license. To learn more, visit www.min.io.
1. Create new project nest new minio-example.
2. Download packages npm i nestjs-minio-s3 @nestjs/config multer, and npm i --save-dev @types/multer.
3. Set docker environment variables in .docker.env:
MINIO_ROOT_USER="minioadmin"
MINIO_ROOT_PASSWORD="minioadmin"
4. Add file docker-compose.yml and new Minio container:
services:
minio:
image: minio/minio:latest
container_name: minio
ports:
- '9000:9000'
- '9001:9001'
env_file:
- .docker.env
command: server /data --console-address ":9001"
volumes:
- minio:/data
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"]
interval: 30s
timeout: 20s
retries: 3
volumes:
minio:
driver: local
5. Start container docker compose up -d
6. Add global environment variables in .env:
MINIO_HOST="localhost"
MINIO_PORT=9000
MINIO_SSL=false
MINIO_USER="minioadmin"
MINIO_PASSWORD="minioadmin"
MINIO_REGION="us-east-1"
7. Include MinioModulein AppModule:
import { Module } from '@nestjs/common';
import {MinioModule} from "nestjs-minio-s3";
import {ConfigModule, ConfigService} from "@nestjs/config";
import { AppController } from './app.controller';
import { AppService } from './app.service';
@Module({
imports: [
ConfigModule.forRoot({
isGlobal: true,
}),
MinioModule.forRootAsync({
imports: [ConfigModule],
inject: [ConfigService],
useFactory: (configService: ConfigService) => ({
host: configService.get('MINIO_HOST')!,
port: +configService.get('MINIO_PORT')!,
useSSL: configService.get('MINIO_SSL') === 'true',
accessKey: configService.get('MINIO_USER')!,
secretKey: configService.get('MINIO_PASSWORD')!,
region: configService.get('MINIO_REGION') || 'us-east-1',
}),
}),
],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}
8. Add new files AvatarsModule, AvatarsService, AvatarsController.
9. Use MinioModule.forFeaturefor creating new Buckets S3:
import {Module} from "@nestjs/common";
import {AvatarsService} from "./avatars.service";
import {AvatarsController} from "./avatars.controller";
import {MinioModule} from "nestjs-minio-s3";
@Module({
imports: [MinioModule.forFeature({bucketName: 'avatars', policy: 'public'})],
providers: [AvatarsService],
controllers: [AvatarsController],
})
export class AvatarsModule {}
10. Use @InjectBucket()in your services:
import {Injectable} from "@nestjs/common";
import {InjectBucket} from "nestjs-minio-s3/dist/decorators/inject-bucket.decorator";
import {MinioService} from "nestjs-minio-s3";
@Injectable()
export class AvatarsService {
constructor(@InjectBucket() private readonly bucketName: string,
private readonly minioService: MinioService) {
}
async uploadAvatar(file: Express.Multer.File) {
const key = `${Date.now()}.${file.originalname.split('.').pop()}`;
return this.minioService.upload(
this.bucketName,
key,
file.buffer,
file.mimetype,
);
}
}
11. And implementing method upload image in controller:
import {Controller, Post, UploadedFile, UseInterceptors} from "@nestjs/common";
import type {Express} from 'express';
import {AvatarsService} from "./avatars.service";
import {FileInterceptor} from "@nestjs/platform-express";
@Controller('avatars')
export class AvatarsController {
constructor(private readonly avatarsService: AvatarsService) {}
@Post()
@UseInterceptors(FileInterceptor('avatar'))
uploadAvatar(@UploadedFile() file: Express.Multer.File) {
return this.avatarsService.uploadAvatar(file);
}
}
12. After completing the request, view the changes at the address http://localhost:9001 with authorization data: username: minioadmin, password: minioadmin
Minio package: nestjs-minio-s3.
GitHub Repository this example: https://github.com/Vodnyy143/nestjs-minio-example.git.
Top comments (4)
Nice writeup, could you explain the need for
InjectBuckethere, as opposed to just using bucket name from a config. Does it auto-create a bucket maybe?Good question! The
InjectBucketapproach gives you flexibility to work with multiple buckets for different categories. For example, you might want one bucket for avatars, another for post photos, and a third for something else.Also, something I didn't mention in the article - you can create buckets like this:
This way you can inject specific buckets where needed and manage different access policies for each one.
Oh, wow this is certainly very useful, thanks
Это великолепно