@mail4entry/nest-file-repository
v0.1.3
Published
file repository for Nest framework
Downloads
2
Readme
nest-file-repository
This library provides a flexible file repository for storing files.
Features
- Provides a flexible file repository
- Support Disk, Memory, AWS S3, GCS(google cloud storage) file repository
- Use
save
for save file,get
for get file,getUrl
for download public file,getSingedUrlForRead
for download private file,getSignedUrlForUpload
for download private file method
Installation
npm install nest-file-repository
yarn add nest-file-repository
If you want to use S3FileRepository
, you have to install @aws-sdk/client-s3
, @aws-sdk/s3-request-presigner
.
npm install nest-file-repository @aws-sdk/client-s3 @aws-sdk/s3-request-presigner
yarn add nest-file-repository @aws-sdk/client-s3 @aws-sdk/s3-request-presigner
If you want to use GCSFileRepository
, you have to install @google-cloud/storage
npm install nest-file-repository @google-cloud/storage
yarn add nest-file-repository @google-cloud/storage
Basic Usage
First, the module we created must be imported into your module
import { Module } from '@nestjs/common';
import { FileRepositoryModule, UploadStrategy } from 'nest-file-repository';
import { YourService } from './your.service'
@Module({
imports: [
FileRepositoryModule.register({
strategy: UploadStrategy.MEMORY,
}),
],
providers: [YourService]
})
export class YourModule {}
Then, Make the file repository available to inject into your service what you want.
Appropriate file repository will be injected via the config you passed when configuring the module.
import { Injectable } from '@nestjs/common';
import { FileRepository, File } from 'nest-file-repository';
import { getBindingIdentifiers } from "@babel/types";
@Injectable()
export class YourService {
constructor(private readonly fileRepository: FileRepository) {
}
async save(filePath: string, fileData: Buffer): Promise<string> {
const path = await this.fileRepository.save(new File(filePath, fileData))
return path;
}
async get(key: string): Promise<File> {
const file = await this.fileRepository.get(key);
if (!file) {
throw new Error("file not found");
}
return file;
}
async getUrl(key: string): Promise<string> {
return this.fileRepository.getUrl(key);
}
async getSignedUrlForRead(key: string): Promise<string> {
return this.fileRepository.getSingedUrlForRead(key)
}
async getSignedUrlForUpload(key: string): Promise<string> {
return this.fileRepository.getSingedUrlForUpload(key)
}
}
If you want to use more than one file repository, you can specify it like this:
First, when importing our module into your module, you must set the name
import { Module } from '@nestjs/common';
import { YourService } from './your.service';
import { FileRepositoryModule, UploadStrategy } from 'nest-file-repository';
@Module({
imports: [
FileRepositoryModule.register({
name: 'sample1',
strategy: UploadStrategy.MEMORY,
}),
FileRepositoryModule.register({
name: 'sample2',
strategy: UploadStrategy.DISK,
options: {
path: './sample2',
},
}),
],
providers: [YourService],
})
export class YourModule {}
Then, you need to @Inject
the FileRepository
into your service.
You must set which file repository it is through Inject.
import { Inject, Injectable } from '@nestjs/common';
import { TestProjectService } from './test-project.service';
import { File, FileRepository } from 'nest-file-repository';
@Injectable()
export class YourService {
constructor(
@Inject('sample1') private readonly fileRepository1: FileRepository,
@Inject('sample2') private readonly fileRepository2: FileRepository,
) {}
async save1(): Promise<string> {
return await this.fileRepository1.save(
new File('test-file.txt', Buffer.from('hello')),
);
}
async save2(): Promise<string> {
return await this.fileRepository2.save(
new File('test-file.txt', Buffer.from('hello')),
);
}
}
Customize
CustomProvider
You can customize some providers. For example, options.uploadOptionFactory
in S3FileRepositoryConfiguration
is type CustomProvider<S3UploadOptionFactory>
.
Type CustomProvider<T>
can be customized in four ways: Type<T>
, CustomClassProvider<T>
, CustomValueProvider<T>
, CustomFactoryProvider<T>
. It is similar to Provider
of NestJS.
Type<T>
If you set implementation of generic type parameter in CustomProvider, then it is replaced by instance of your customized class.
import { Injectable } from '@nestjs/common';
import { S3UploadOptionFactory } from 'nest-file-repository';
@Injectable()
class CustomS3UploadOptionFactory implements S3UploadOptionFactory {
getOptions(
file: File,
config: S3FileRepositoryConfiguration,
): S3UploadOption {
return {
bucket: config.options.bucket,
key: file.filename,
body: file.data,
};
}
}
import { Module } from '@nestjs/common';
import { YourService } from './your.service';
import { FileRepositoryModule, UploadStrategy } from 'nest-file-repository';
@Module({
imports: [
FileRepositoryModule.register({
strategy: UploadStrategy.S3,
options: {
region: 'your region',
bucket: 'your bucket',
acl: 'public-read', // acl of your bucket
credentials: {
accessKeyId: 'your access key id',
secretAccessKey: 'your secret access key',
},
uploadOptionFactory: CustomS3UploadOptionFactory,
},
})
],
providers: [YourService],
})
export class YourModule {}
CustomClassProvider<T>
It works almost the same as the Type<T>
.
import { Module } from '@nestjs/common';
import { YourService } from './your.service';
import { FileRepositoryModule, UploadStrategy } from 'nest-file-repository';
@Module({
imports: [
FileRepositoryModule.register({
strategy: UploadStrategy.S3,
options: {
region: 'your region',
bucket: 'your bucket',
acl: 'public-read', // acl of your bucket
credentials: {
accessKeyId: 'your access key id',
secretAccessKey: 'your secret access key',
},
uploadOptionFactory: { useClass: CustomS3UploadOptionFactory }
},
})
],
providers: [YourService],
})
export class YourModule {}
CustomValueProvider<T>
If you set instance of generic type parameter in CustomProvider, then it is replaced by the value.
import { Module } from '@nestjs/common';
import { YourService } from './your.service';
import { FileRepositoryModule, UploadStrategy } from 'nest-file-repository';
@Module({
imports: [
FileRepositoryModule.register({
strategy: UploadStrategy.S3,
options: {
region: 'your region',
bucket: 'your bucket',
acl: 'public-read', // acl of your bucket
credentials: {
accessKeyId: 'your access key id',
secretAccessKey: 'your secret access key',
},
uploadOptionFactory: { useValue: new CustomS3UploadOptionFactory() }
},
})
],
providers: [YourService],
})
export class YourModule {}
CustomFactoryProvider<T>
If you want to customize implementation requiring DI, can use CustomFactoryProvider
.
@Injectable()
class CustomS3UploadOptionFactory implements S3UploadOptionFactory {
constructor(private readonly nameGenerator: NameGenerator) {}
getOptions(
file: File,
config: S3FileRepositoryConfiguration,
): S3UploadOption {
return {
bucket: config.options.bucket,
key: this.nameGenerator.generate(file),
body: file.data,
};
}
}
Prepare a module with provider to be injected. If the global module contains the value you want to inject, it is not necessary.
@Module({
providers: [IdentityNameGenerator],
exports: [IdentityNameGenerator],
})
class NameGeneratorModule {
}
Import prepared modules, inject provider you want and set factory function. Then it is replaced by return value of factory function.
@Module({
imports: [
FileRepositoryModule.register({
strategy: UploadStrategy.S3,
options: {
region: 'your region',
bucket: 'your bucket',
acl: 'public-read', // acl of your bucket
credentials: {
accessKeyId: 'your access key id',
secretAccessKey: 'your secret access key',
},
uploadOptionFactory: {
import: [NameGeneratorModule],
useFactory: (nameGenerator: NameGenerator) => new CustomS3UploadOptionFactory(nameGenerator),
inject: [IdentityNameGenerator]
}
},
})
],
providers: [YourService],
})
export class YourModule {
}
options
common options
strategy
(required): Select upload strategy of FileRepository. ExistMEMORY
,DISK
,S3
strategy.name
: Set name of your FileRepository. It is required if you want to use two or more file repositories.options.timeout
: Set timeout. The number of milliseconds a request can take before automatically being terminated. 0 disables the timeout.options.path
: Set save path.
S3 options
region
(required): Set the region where your bucket is located.credentials.accessKeyId
(required): Set an access key id with access to AWS s3.credentials.secretAccessKey
(required): Set a secret access key with access to AWS s3.bucket
(required): Set your bucket.acl
: Set available acl on your bucket.endPoint
: Set AWS endpoint.forcePathStyle
: Whether to force path style URLs for S3 objects (e.g.,https://s3.amazonaws.com/<bucketName>/<key>
instead ofhttps://<bucketName>.s3.amazonaws.com/<key>
.uploadOptionFactory
: Set the implementation of theS3UploadOptionFactory
. By default, theDefaultS3UploadOptionFactory
is used.
GCS options
bucket
(required): Set your bucket.acl
: Set available acl on your bucket.apiEndPoint
: Set your api endpoint.projectId
: Set your project id. If not provided, the library will attempt to automatically detect the project ID based on the environment.keyFile
: Set your keyfile path.uploadOptionFactory
: Set the implementation of theGCSUploadOptionFactory
. By default, theDefaultGCSUploadOptionFactory
is used.
Exception
TimeoutException
: Times outNoSuchBucketException
: Does not exist s3 or gcs bucket.InvalidAccessKeyIdException
: Invalid access key id of s3NotAllowedAclException
: Not allowed acl of s3 bucketSignatureDoesNotMatchedException
: Not matched access key id and secret access key of s3
License
This library is licensed under the MIT license.