title: How can I add custom validation to a file upload with OpenAPI 3 in SpringBoot?
body: <p>I want to add custom validation to a file upload in Spring using OpenAPI3. The file will be an excel file that should be validated that it is of:</p>
  <ul>
  <li>type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet</li>
  <li>size: smaller than 20MB</li>
  </ul>
  <p>This is the endpoint in the api.yaml:</p>
  <pre class="lang-yaml prettyprint-override"><code>/documentUpload:
    post:
      tags:
        - My Excel Upload
      summary: Excel document upload
      description: Upload a document that is an excel file
      operationId: uploadDocument
      requestBody:
        content:
          multipart/form-data:
            schema:
              $ref: '#/components/schemas/DocumentUploadRequest'
      responses:
        '202':
          description: Document recieved.
  </code></pre>
  <p>and the request object:</p>
  <pre class="lang-yaml prettyprint-override"><code>DocumentUploadRequest:
    type: object
    description: Upload a document together with metadata for it
    required:
      - type
      - file
    properties:
      type:
        $ref: '#/components/schemas/DocumentType'
      file:
        type: string
        format: binary
        description: Document in binary format
  </code></pre>
  <p>and here the controller method from where I want to override the generated API method:</p>
  <pre class="lang-java prettyprint-override"><code>@Override
  public ResponseEntity&lt;Void&gt; uploadDocument(
      DocumentType type,
      MultipartFile file) {
  
      // Validation required
  
      return ResponseEntity.ok().build();
  }
  </code></pre>
  <p>Since I cannot use @Valid on the file parameter, because it is already defined in the super class (on all parameters by default), I tried to write a custom Validator (using org.springframework.validation.Validator) like this:</p>
  <pre class="lang-java prettyprint-override"><code>@Component
  public class MyFileValidator implements Validator {
      
    private static final int MAX_FILE_SIZE = 20000000;
    private static final String ALLOWED_FILE_TYPE = &quot;application/vnd.openxmlformats-officedocument.spreadsheetml.sheet&quot;;
      
    @Override
    public boolean supports(Class&lt;?&gt; aClass) {
      if (aClass.isInstance(MassChangeDocumentType.class)) {
        return true;
      }
      return MultipartFile.class.isAssignableFrom(aClass);
    }
      
    @Override
    public void validate(Object target, Errors errors) {
      ValidationUtils.rejectIfEmpty(errors, &quot;file&quot;, &quot;file.empty&quot;);
      MultipartFile file = (MultipartFile) target;
      rejectIfFileTypeInvalid(errors, file);     
      rejectIfFileIsTooLarge(errors, file);
    }
    ...
  </code></pre>
  <p>And added this Validation to the Controller class using the @InitBinder annotation:</p>
  <pre class="lang-java prettyprint-override"><code>@RestController
  @RequiredArgsConstructor
  public class DocumentUploadController implements DocumentUploadApi {
      
    private final MyFileValidator fileValidator;
  
    @InitBinder
    protected void initBinder(WebDataBinder binder) {
      if (binder.getTarget() == null) {
        return;
      }
      if (binder.getTarget().getClass().isAssignableFrom(MultipartFile.class)) {
        binder.addValidators(fileValidator);
      }
    }
  
    @Override
    public ResponseEntity&lt;Void&gt; uploadDocument(
      DocumentType type,
      MultipartFile file) {
      
      // Validation required
      
      return ResponseEntity.ok().build();
    }
  ...
  </code></pre>
  <p>The result with this is that only the type argument is being evaluated in the initBinder method. The file argument is being ignored and not validated at all. Am I even using the correct approach for this kind of custom validation?</p>