I created my own dynamic module to setup file upload for my project.
But when I try to inject service from my module in registerAsync
method of MulterModule, I get this error:
Error: Nest can't resolve dependencies of the MULTER_MODULE_OPTIONS (?). Please make sure that the argument UploadsService at index [0] is available in the MulterModule context.
Potential solutions:
- If UploadsService is a provider, is it part of the current MulterModule?
- If UploadsService is exported from a separate @Module, is that module imported within MulterModule?
@Module({
imports: [ /* the Module containing UploadsService */ ]
})
UploadsModule.forRoot({
endpoint: process.env.S3_ENDPOINT,
accessKey: process.env.S3_ACCESS_KEY,
secretKey: process.env.S3_SECRET_KEY,
bucket: 'testbucket',
}),
MulterModule.registerAsync({
imports: [UploadsModule],
inject: [UploadsService],
useFactory: (uploadsService: UploadsService) => ({
storage: uploadsService.getS3MulterStorage(),
}),
}),
I followed this guide from NestJS Docs and code of my UploadsModule is:
import { DynamicModule, Module } from '@nestjs/common';
import { UploadsService } from './uploads.service';
import { UploadsModuleOptions } from './uploads.types';
@Module({})
export class UploadsModule {
static forRoot(options: UploadsModuleOptions): DynamicModule {
return {
module: UploadsModule,
providers: [
{
provide: 'UPLOADS_MODULE_OPTIONS',
useValue: options,
},
UploadsService,
],
exports: [UploadsService],
};
}
}
And this is code of my UploadsService:
@Injectable()
export class UploadsService {
private readonly client: S3Client;
private readonly bucket: string;
private readonly multerStorage: StorageEngine;
constructor(
@Inject('UPLOADS_MODULE_OPTIONS')
private readonly options: UploadsModuleOptions,
) {
this.client = new S3Client({
endpoint: options.endpoint,
credentials: {
accessKeyId: options.accessKey,
secretAccessKey: options.secretKey,
},
});
this.bucket = options.bucket;
this.multerStorage = multerS3({
s3: this.client,
bucket: this.bucket,
acl: 'private',
metadata: (req, file, cb) => {
cb(null, { fieldName: file.fieldname });
},
key: (req, file, cb) => {
cb(null, file.originalname + '-' + Date.now());
},
});
}
getS3MulterStorage() {
return this.multerStorage;
}
}
UploadsModule exports UploadsService, registerAsync
method of MulterModule imports my UploadsModule and therefore must be able to inject UploadService?
Only your UploadsModule.forRoot()
provides the exports
of UploadsService
, so when you use imports: [UploadsModule]
you don't get the same providers exported. What I would suggest is create a separate module that does and import and export of the UploadsModule
so you can import the wrapper and make use of module re-exporting
@Module({
imports: [UploadsModule.forRootAsync(uploadModuleOptions)],
exports: [UploadsModule]
})
export class WrapperUploadsModule {}
MulterModule.registerAsync({
imports: [WrapperUploadsModule],
inject: [UploadsService],
useFactory: (uploadsService: UploadsService) => ({
storage: uploadsService.getS3MulterStorage(),
}),
}),
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.