Skip to main content

@nestjs-mod/minio

Minio client for NestJS-mod (Wrapper for https://www.npmjs.com/package/nestjs-minio)

NPM version monthly downloads Telegram Discord

Installation

npm i --save minio@7.1.3 nestjs-minio@2.5.4 @nestjs-mod/minio

Modules

LinkCategoryDescription
MinioModulecoreMinio client for NestJS-mod (Wrapper for https://www.npmjs.com/package/nestjs-minio)

Modules descriptions

MinioModule

Minio client for NestJS-mod (Wrapper for https://www.npmjs.com/package/nestjs-minio)

Use in NestJS

A simple example of generating a link to upload and download a picture.

import { NestFactory } from '@nestjs/core';

import { DefaultBucketNames, MinioFilesService, MinioModule, PresignedUrlsRequest } from '@nestjs-mod/minio';
import { Controller, Get, Module, Query } from '@nestjs/common';
import { lastValueFrom } from 'rxjs';

@Controller()
export class AppController {
constructor(private readonly minioFilesService: MinioFilesService) {}

@Get('images-presigned-url')
getImagesPresignedUrl(@Query() request: PresignedUrlsRequest) {
return this.minioFilesService.getPresignedUrls({
bucketName: DefaultBucketNames.images,
expiry: 60,
ext: request.ext,
});
}

@Get('video-presigned-url')
getVideoPresignedUrl(@Query() request: PresignedUrlsRequest) {
return this.minioFilesService.getPresignedUrls({
bucketName: DefaultBucketNames.video,
expiry: 60,
ext: request.ext,
});
}

@Get('documents-presigned-url')
getDocumentsPresignedUrl(@Query() request: PresignedUrlsRequest) {
return this.minioFilesService.getPresignedUrls({
bucketName: DefaultBucketNames.documents,
expiry: 60,
ext: request.ext,
});
}
}

process.env.MINIO_SERVER_HOST = 'localhost';
process.env.MINIO_SERVER_PORT = '9000';
process.env.MINIO_ACCESS_KEY = 'minioadmin';
process.env.MINIO_SECRET_KEY = '6EcbcW66JsKvFrY2bZw6QGKjHhefca7Kgppq';
process.env.MINIO_USE_SSL = 'false';
process.env.MINIO_DEFAULT_USER_ID = 'default';

@Module({
imports: [MinioModule.forRoot()],
controllers: [AppController],
})
export class AppModule {}

async function bootstrap() {
const app = await NestFactory.create(AppModule);
await app.listen(3000);

const appController = app.get<AppController>(AppController);
console.log(await lastValueFrom(appController.getImagesPresignedUrl({ ext: 'png' })));
/**
* output:
* {
* uploadUrl: '/images/default/images_ac98618c-f2ec-4a2f-a4a8-a4690e8fd543.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Date=20240213T071934Z&X-Amz-Expires=60&X-Amz-SignedHeaders=host&X-Amz-Signature=ea5c4246876c0c15a57e7c6cb0035fb3122c4887b052d2138d643f3e88e8a4c3',
* downloadUrl: '/images/default/images_ac98618c-f2ec-4a2f-a4a8-a4690e8fd543.png'
* }
*/
}

bootstrap();

Use in NestJS-mod

An example of using Minio, you can see the full example here https://github.com/nestjs-mod/nestjs-mod-contrib/tree/master/apps/example-minio and frontend on Angular here https://github.com/nestjs-mod/nestjs-mod-contrib/tree/master/apps/example-minio-angular.

For work with Minio, you must first connect the Docker Compose module and the Docker Compose module to work with the Minio.

import {
DefaultNestApplicationInitializer,
DefaultNestApplicationListener,
InfrastructureMarkdownReportGenerator,
PACKAGE_JSON_FILE,
ProjectUtils,
bootstrapNestApplication,
createNestModule,
isInfrastructureMode,
} from '@nestjs-mod/common';
import { DefaultBucketNames, MinioFilesService, MinioModule, PresignedUrlsRequest } from '@nestjs-mod/minio';
import { Controller, Get, Query } from '@nestjs/common';
import { join } from 'path';
import { lastValueFrom } from 'rxjs';
import { userFeatureName } from './app/app.constants';

import { DOCKER_COMPOSE_FILE, DockerCompose, DockerComposeMinio } from '@nestjs-mod/docker-compose';

@Controller()
export class AppController {
constructor(private readonly minioFilesService: MinioFilesService) {}

@Get('images-presigned-url')
getImagesPresignedUrl(@Query() request: PresignedUrlsRequest) {
return this.minioFilesService.getPresignedUrls({
bucketName: DefaultBucketNames.images,
expiry: 60,
ext: request.ext,
});
}

@Get('video-presigned-url')
getVideoPresignedUrl(@Query() request: PresignedUrlsRequest) {
return this.minioFilesService.getPresignedUrls({
bucketName: DefaultBucketNames.video,
expiry: 60,
ext: request.ext,
});
}

@Get('documents-presigned-url')
getDocumentsPresignedUrl(@Query() request: PresignedUrlsRequest) {
return this.minioFilesService.getPresignedUrls({
bucketName: DefaultBucketNames.documents,
expiry: 60,
ext: request.ext,
});
}
}

const { AppModule } = createNestModule({
moduleName: 'AppModule',
imports: [MinioModule.forFeature()],
controllers: [AppController],
});

const rootFolder = join(__dirname, '..', '..', '..');
const appFolder = join(rootFolder, 'apps', 'example-minio');

bootstrapNestApplication({
globalConfigurationOptions: { debug: true },
globalEnvironmentsOptions: { debug: true },
modules: {
system: [
ProjectUtils.forRoot({
staticConfiguration: {
applicationPackageJsonFile: join(appFolder, PACKAGE_JSON_FILE),
packageJsonFile: join(rootFolder, PACKAGE_JSON_FILE),
envFile: join(rootFolder, '.env'),
},
}),
DefaultNestApplicationInitializer.forRoot({
staticConfiguration: {
bufferLogs: true,
},
}),
DefaultNestApplicationListener.forRoot({
staticConfiguration: {
// When running in infrastructure mode, the backend server does not start.
mode: isInfrastructureMode() ? 'silent' : 'listen',
postListen: async ({ app }) => {
if (app) {
const appController = app.get<AppController>(AppController);
console.log(await lastValueFrom(appController.getImagesPresignedUrl({ ext: 'png' })));
/**
* output:
* {
* uploadUrl: '/images/default/images_ac98618c-f2ec-4a2f-a4a8-a4690e8fd543.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Date=20240213T071934Z&X-Amz-Expires=60&X-Amz-SignedHeaders=host&X-Amz-Signature=ea5c4246876c0c15a57e7c6cb0035fb3122c4887b052d2138d643f3e88e8a4c3',
* downloadUrl: '/images/default/images_ac98618c-f2ec-4a2f-a4a8-a4690e8fd543.png'
* }
*/
}
},
},
}),
],
core: [MinioModule.forRoot()],
feature: [AppModule.forRoot()],
infrastructure: [
InfrastructureMarkdownReportGenerator.forRoot({
staticConfiguration: {
markdownFile: join(appFolder, 'INFRASTRUCTURE.MD'),
skipEmptySettings: true,
},
}),
DockerCompose.forRoot({
configuration: {
dockerComposeFileVersion: '3',
dockerComposeFile: join(appFolder, DOCKER_COMPOSE_FILE),
},
}),
DockerComposeMinio.forRoot({
staticConfiguration: {
nginxPort: 1111,
nginxFilesFolder: join(appFolder, 'ngnix'),
featureName: userFeatureName,
},
}),
],
},
});

New environment variable

EXAMPLE_MINIO_MINIO_SERVER_HOST=localhost
EXAMPLE_MINIO_MINIO_SERVER_PORT=9000
EXAMPLE_MINIO_MINIO_ACCESS_KEY=minioadmin
EXAMPLE_MINIO_MINIO_SECRET_KEY=6EcbcW66JsKvFrY2bZw6QGKjHhefca7Kgppq
EXAMPLE_MINIO_MINIO_USE_SSL=false
EXAMPLE_MINIO_MINIO_DEFAULT_USER_ID=default
EXAMPLE_MINIO_PORT=3006
EXAMPLE_MINIO_HOSTNAME=

When launched in the infrastructure documentation generation mode, the module creates an .env file with a list of all required variables, as well as an example example.env, where you can enter example variable values.

Shared providers

MinioService, MinioFilesService

Static environments

KeyDescriptionSourcesConstraintsDefaultValue
minioServerHostServer hostobj['minioServerHost'], process.env['MINIO_SERVER_HOST']isNotEmpty (minioServerHost should not be empty)--
minioServerPortServer portobj['minioServerPort'], process.env['MINIO_SERVER_PORT']optional90009000
minioAccessKeyAccess keyobj['minioAccessKey'], process.env['MINIO_ACCESS_KEY']isNotEmpty (minioAccessKey should not be empty)--
minioSecretKeySecret keyobj['minioSecretKey'], process.env['MINIO_SECRET_KEY']isNotEmpty (minioSecretKey should not be empty)--
minioUseSSLUse SSLobj['minioUseSSL'], process.env['MINIO_USE_SSL']optionalfalsefalse
minioDefaultUserIdDefault user idobj['minioDefaultUserId'], process.env['MINIO_DEFAULT_USER_ID']optionaldefaultdefault

Static configuration

KeyDescriptionConstraintsDefaultValue
featureNameFeature name for generate prefix to environments keysoptional--
regionRegionoptionalus-east-1-
transportTransportoptional--
sessionTokenSession tokenoptional--
partSizePart sizeoptional--
pathStyleConfig options nameoptionaltrue-
credentialsProviderCredentials provideroptional--
s3AccelerateEndpointS3 accelerate endpointoptional--
transportAgentTransport agentoptional--
bucketsBuckets with policyoptional{"images":{"policy":{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Principal":{"AWS":["*"]},"Action":["s3:PutObject","s3:AbortMultipartUpload","s3:DeleteObject","s3:GetObject"],"Resource":["arn:aws:s3:::images/*.jpg","arn:aws:s3:::images/*.jpeg","arn:aws:s3:::images/*.png","arn:aws:s3:::images/*.gif"]}],"Conditions":[["content-length-range",5242880]]},"ext":["jpg","jpeg","png","gif"]},"video":{"policy":{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Principal":{"AWS":["*"]},"Action":["s3:PutObject","s3:AbortMultipartUpload","s3:DeleteObject","s3:GetObject"],"Resource":["arn:aws:s3:::video/*.mp4"]}],"Conditions":[["content-length-range",52428800]]},"ext":["mp4"]},"documents":{"policy":{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Principal":{"AWS":["*"]},"Action":["s3:PutObject","s3:AbortMultipartUpload","s3:DeleteObject","s3:GetObject"],"Resource":["arn:aws:s3:::documents/*.doc","arn:aws:s3:::documents/*.docx","arn:aws:s3:::documents/*.xls","arn:aws:s3:::documents/*.md","arn:aws:s3:::documents/*.odt","arn:aws:s3:::documents/*.txt","arn:aws:s3:::documents/*.xml","arn:aws:s3:::documents/*.rtf","arn:aws:s3:::documents/*.csv"]}],"Conditions":[["content-length-range",10485760]]},"ext":["doc","docx","xls","md","odt","txt","xml","rtf","csv"]}}-

Back to Top

License

MIT