0

I wanna create an Interceptor of nestjs and on this level and want to do uploading file. I can't find a solution, how to resolve this code by Observable (https://github.com/fastify/fastify-multipart)

I'm using fromPromise but with this tool, I've more problems. Because I can resolve only once. I need for each file do validation and if validation returns resolve then run pump for writing.

const mp = req.multipart(handler, function (err) {
    console.log('upload completed')
    reply.code(200).send()
  })
  // handler wil run for each file
  function handler (field, file, filename, encoding, mimetype) {
    // to accumulate the file in memory! Be careful!
    //
    // file.pipe(concat(function (buf) {
    //   console.log('received', filename, 'size', buf.length)
    // }))
    //
    // or

    pump(file, fs.createWriteStream('a-destination'))

    // be careful of permission issues on disk and not overwrite
    // sensitive files that could cause security risks
  }

I use this code, for my old case it's enough...

const obs1$ = fromPromise(new Promise((res, rej) => {
            const mp = request.multipart((field, file, filename, encoding, mimetype) => {
                const writeStream = fs.createWriteStream('path');
                //here need run onValidation
                pump(file, writeStream);
            }, (err) => {
                //doSuccess
                (err) ? rej(err) : res();
            });
        }));

        return obs1$.pipe(
            catchError(error => {
                throw new BadRequestException(error);
            }),
            switchMap(() => {
                request.body = body;
                return next.handle();
            }), mergeAll());

but I've a new case (I need do validation before file will be save) and case is: next.hander() return Observable with some methods:

@Controller('test')
export class TestCtrl {

@Post('upload')
@UseInterceptors(new FileInterceptor())
    uploadFile() {
        return {
            onValidate: (file: IFiles) => {
                console.log(this.tst);
                return Promise.resolve(true);
            },
            onSuccess: () => {
                return Promise.resolve(true);
            }
        };
    }
}

Tried something like that:

@Injectable()
export class FileInterceptor implements NestInterceptor {

    intercept(context: any, next: CallHandler): Observable<any> {
        const request = context.getRequest();
        const body: Array<any> = [];

        return next.handle().pipe(switchMap((methods: any) => {
            const mp = request.multipart((field, file, filename, encoding, mimetype) => {
                const writeStream = fs.createWriteStream('path');
                body.push({
                    filename, file
                });

                methods.onValidation(file).then(() => {
                    pump(file, writeStream);
                }).catch(() => {
                    writeStream.destroy();
                });
            }, () => {
                //done
                methods.onSuccess(body); // how to return this?
            });
            return null; // ???
        }));

 }
}
rysalka
  • 51
  • 1
  • 7

1 Answers1

0

I almost resolve my problem by bindNodeCallback and then I wrote my own bindNodeCallback method which can resolve my case with double callbacks.

callbackFunc.apply(context, [...args, handler1, handler2, handler3]);
rysalka
  • 51
  • 1
  • 7