1

I am creating a interceptor Inside that I want to use FileInterceptor but I am getting error Declaration Expected after FileInterceptor

import { CallHandler, ExecutionContext, Injectable, NestInterceptor, UseInterceptors } from '@nestjs/common';
import { Observable } from 'rxjs';
import { FileInterceptor } from '@nestjs/platform-express';
import { diskStorage } from 'multer';
import { extname } from 'path';

@Injectable()
export class UploaderInterceptor implements NestInterceptor {
  intercept(context: ExecutionContext, next: CallHandler): Observable<any> {

    @UseInterceptors(FileInterceptor('file', {
      storage: diskStorage({
          destination: './uploads'
          , filename: (req, file, cb) => {
              // Generating a 32 random chars long string
              const randomName = Array(32).fill(null).map(() => (Math.round(Math.random() * 16)).toString(16)).join('')
              //Calling the callback passing the random name generated with the original extension name
              cb(null, `${randomName}${extname(file.originalname)}`)
          }
      })
  }));


    return next.handle();
  }
}
Akhilesh Jha
  • 23
  • 3
  • 9
  • What's the reason for wanting to use an interceptor inside an interceptor? Do you just need to extend the functionality? Currently, that interceptor is applied to nothing, and in NestJS, the `UseInterceptors()` decorator only applies when you bind it to a controller or a route handler. – Jay McDoniel Apr 08 '20 at 06:19
  • @JayMcDoniel Yes I want to extend the functionality. Basically what I want instead of calling FileInterceptor and provide all the argument I will only call UploaderInterceptor and this Interceptor will do rest of the thing – Akhilesh Jha Apr 08 '20 at 06:24
  • I see using an alias being much more efficient here. Something like `export const UploadInterceptor = FileInterceptor(config)` and then using `@UseInterceptors(UploadInterceptor)` instead of working with TS class stuff like this. – Jay McDoniel Apr 08 '20 at 06:30
  • @JayMcDoniel but FileInterceptor will not work without using UseInterceptors. Can you please write it in code what you want to say me – Akhilesh Jha Apr 08 '20 at 06:48
  • @JayMcDoniel but without using UseInterceptors how FileInterceptor will work – Akhilesh Jha Apr 08 '20 at 10:54

1 Answers1

3

FileInterceptor is a mixin meaning it is a function that returns a class. This function takes in a configuration for the interceptor to actually use. What you can do instead of trying to make a class that makes use of the interceptor under the hood or extends it, is essentially make an alias for the configuration like so:

export const UploadInterceptor = FileInterceptor('file', {
  storage: diskStorage({
      destination: './uploads',
      filename: (req, file, cb) => {
        // Generating a 32 random characters long string
        const randomName = Array(32).fill(null).map(() => (Math.round(Math.random() * 16)).toString(16)).join('')
        //Calling the callback passing the random name generated with the original extension name
        cb(null, `${randomName}${extname(file.originalname)}`)
      }
  })
})

Now with this exported constant (that is actually a class), you can then make use of the interceptor as such:

@Controller('upload')
export class UploadController {

  @UseInterceptors(UploadInterceptor)
  @Post()
  uploadFile() {
  // do logic;
  }
}

And everything should work out for you.

Matt Brandt
  • 581
  • 1
  • 4
  • 20
Jay McDoniel
  • 57,339
  • 7
  • 135
  • 147
  • but without using UseInterceptors how FileInterceptor will work . – Akhilesh Jha Apr 08 '20 at 07:40
  • @AkhileshJha Like I said in the beginning, `FileInterceptor` is nothing more than a function that returns a class. With the above, `UploadInterceptor` is essentially an alias for `FileInterceptor(config)`. There' no reason to use `@UseInterceptor()` when it comes to making this alias, it's only necessary when it comes to binding the interceptor to a controller or to a route. You can see in my answer as well, that's exactly what happens. – Jay McDoniel Apr 08 '20 at 15:16