Search code examples
angularfile-uploaduploadpostmannestjs

Angular 16 and Nestjs: Upload files it's impossible (With Postman works perfect)


I'm trying to upload a file from Angular 16 (localhost:4200) to Nestjs 10 (localhost:3000), with cors enabled. This is my code:

Angular:

<!-- html -->
<input type="file" name="file" class="form-control" (change)="onChange($event)" />
// Typescript component
onChange(event: Event) {
    const target = event.target as HTMLInputElement;
    const file = target.files?.[0];
    if (file) {
      const formData = new FormData();
      formData.append('file', file, file.name);
      this.apiService.uploadFile(formData, "1").subscribe();
    }
  }
// apiService
uploadFile(formData: FormData, id: string) {
    const params = new HttpParams().set('id', id);
    const headers = new HttpHeaders().set('Content-Type', 'multipart/form-data');

    return this.http.post<FormData>(`${environment.server_url}/files/upload`, {...formData}, {headers, params});
}

Until this code, the request is made.

NestJs: Remember: this code works fine with postman but not with Angular.

@Post('upload')
  @UseInterceptors(
    FileInterceptor('file', {
      fileFilter: fileFilter,
      storage: diskStorage({
        destination: './static',
        filename: fileNamer,
      }),
    }),
  )
  async upload(
    @UploadedFile() file: Express.Multer.File,
    @Query('id') id: string,
    @Res() res: Response,
  ) {
    console.log('file:', file, 'id:', id);
    if (!file) {
      throw new BadRequestException('No Files');
    }

    await this.filesService.saveFileReference(file.filename, id);

    return res.status(HttpStatus.OK).json({
      status: 'ok',
      message: 'success',
    });
  }

Note: I have the following configuration in main.ts (nestjs):

import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { ValidationPipe } from '@nestjs/common';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  app.enableCors();
  app.useGlobalPipes(
    new ValidationPipe({
      whitelist: true,
      forbidNonWhitelisted: true,
    }),
  );
  await app.listen(3000);
}
bootstrap();


Solution

  • Could you try setting the header for 'Accept', '*/*' and do not de-structure the formData, instead send it directly.

    uploadFile(formData: FormData, id: string) {
        const params = new HttpParams().set('id', id);
        const headers = new HttpHeaders()
        headers = headers.append('Content-Type', 'multipart/form-data');
        headers = headers.append('Accept', '*/*');
    
        return this.http.post<FormData>(`${environment.server_url}/files/upload`, formData, {headers, params});
    }