dmitriy-nz / nestjs-form-data

NestJS middleware for handling multipart/form-data, which is primarily used for uploading files.
https://www.npmjs.com/package/nestjs-form-data
MIT License
117 stars 23 forks source link

IsOptional() not work #55

Closed summivar closed 2 months ago

summivar commented 8 months ago

export class EditDto { @ApiProperty({ description: 'Имя услуги', example: 'Имя', required: false }) @IsString() @IsOptional() name: string;

@ApiProperty({ description: 'Описание услуги', example: 'Описание', required: false }) @IsString() @IsOptional() description: string;

@ApiProperty({ type: 'string', format: 'binary', description: 'Картинка услуги', name: 'image', required: false }) @IsFile() @MaxFileSize(1e7, { message: 'File size should not exceed 10MB' }) @HasMimeType(['image/jpeg', 'image/png'], { message: 'File should be a JPEG or PNG image' }) @IsOptional() image?: Express.Multer.File; }

return from server: { "statusCode": 400, "message": "Validation error", "errors": [ { "field": "image", "error": "File should be a JPEG or PNG image, File size should not exceed 10MB, Field \"image\" does not contain file" } ] }

I want to create "UpdateDTO" and don't know how to do this "IsFile" optional

dmitriy-nz commented 8 months ago

@summivar Hi, has a separate test on for this and it passes successfully, you need to check if you are doing everything accurately according to the documentation. Test source Test source DTO

You should also consider that you are using the wrong file type in your dto, class-validator/class-transformer uses this too. The uploaded file is never Express.Multer.File It is an instance of one of the [storage](It is an instance of one of the repositories you use when connecting the module. ) you use when connecting the module.

If you don't find the problem, please create a repository to reproduce the problem and it will be fixed.

julianpoemp commented 6 months ago

@dmitriy-nz i have the same issue with the latest version. My code:


  /**
   * appending files
   */
  @Expose()
  @Transform(({ value }) => {
    return value !== undefined && !Array.isArray(value) ? [value] : value;
  })
  @IsFiles()
  @HasMimeType(['image/jpg', 'image/png', 'application/json', 'text/plain', 'application/xml'])
  @IsOptional()
  appending?: FileHashStorage[];

Event if it's optional the mimetypes are validated as invalid. Same with "IsFiles". I think it only happens if you have an array of files.

TidianeRolland commented 5 months ago

I have the same issue.

import {
  IsInt,
  IsNotEmpty,
  IsNumber,
  IsOptional,
  IsString,
  Min,
} from 'class-validator';
import {
  FileSystemStoredFile,
  HasMimeType,
  IsFile,
  IsFiles,
  MaxFileSize,
} from 'nestjs-form-data';
import { Types } from 'mongoose';
import { Transform, TransformFnParams, Type } from 'class-transformer';

const transformDateFn = (params: TransformFnParams) =>
  params.obj[params.key] === '' || params.obj[params.key] === 'null'
    ? null
    : params.value;

export class CreateAnnonceDto {
  @Transform(transformDateFn)
  @IsNotEmpty()
  @IsString()
  titre: string;

  @Transform(transformDateFn)
  @IsString()
  description: string;

  @IsFile()
  @MaxFileSize(3e6)
  @HasMimeType(['image/jpeg', 'image/png'])
  primary_image: FileSystemStoredFile;

  @IsOptional()
  @IsFiles()
  @MaxFileSize(4e6, { each: true })
  @HasMimeType(['image/jpeg', 'image/png'], { each: true })
  images: FileSystemStoredFile[];
}

IsOptional doesn't work on an array of files. The user is forced to upload at least one file.

Does someone has a solution please ?

dmitriy-nz commented 2 months ago

@summivar @julianpoemp @TidianeRolland Hi! Issue has been reproduced in fixed in the v1.9.9 version, please try it out

julianpoemp commented 2 months ago

@dmitriy-nz still not working for me with v1.9.9


  @Expose()
  @IsOptional()
  @IsFiles()
  appending?: FileHashStorage[];

appending should be optional, but I still get an error if no files appended.

dmitriy-nz commented 2 months ago

@julianpoemp can you share your ValidationPipe options?

julianpoemp commented 2 months ago

@dmitriy-nz

{
        transform: true,
        whitelist: true,
        enableDebugMessages: true,
        forbidNonWhitelisted: true,
        disableErrorMessages: false,
        skipNullProperties: true,
        skipUndefinedProperties: true,
        exceptionFactory: (validationErrors: ValidationError[] = []) => {
          Logger.error(JSON.stringify(validationErrors, null, 2));
          return new BadRequestException(validationErrors);
        },
      }
1155JamalAhmed commented 2 months ago

@julianpoemp if you are like me and testing the apis on postman make sure you uncheck the field in the postman in your case you need to uncheck appending.

dmitriy-nz commented 2 months ago

Thank everyone for the feedback, your case has been reproduced, the issue was that when a property is decorated with Exposed() we are forcing get an undefined value when no value is provided. I have deployed a new version 1.9.91, please try it out @julianpoemp

julianpoemp commented 2 months ago

@dmitriy-nz it's working, thank you! 🎉