Spring StandardMultipartHttpServletRequest 验证

Spring StandardMultipartHttpServletRequest validation

有没有可能验证StandardMultipartHttpServletRequest using standard @Valid annotation and custom Validator

我已经实现了这样的验证器,控制器中的注释方法参数不会调用验证器。

我自己想出来了。要使其工作,您需要一个 DTO:

import lombok.Getter;
import lombok.Setter;
import org.springframework.web.multipart.MultipartFile;

import java.util.List;

@Getter
@Setter
public class NewOrderFilesDTO {
    List<MultipartFile> files;
}

然后,一个验证器:

import org.springframework.stereotype.Component;
import org.springframework.validation.Errors;
import org.springframework.validation.Validator;
import org.springframework.web.multipart.MultipartFile;

import java.util.List;

import static org.springframework.util.CollectionUtils.isEmpty;

@Component
public class NewOrderFilesValidator implements Validator {

    private static final String MIME_TYPE_PDF = "application/pdf";
    private static final long ALLOWED_SIZE = 3 * 1024 * 1024;

    @Override
    public void validate(Object target, Errors errors) {
        if (target == null) {
            return;
        }

        NewOrderFilesDTO newOrderFilesDTO = (NewOrderFilesDTO) target;
        List<MultipartFile> newOrderFiles = newOrderFilesDTO.getFiles();

        if (isEmpty(newOrderFiles)) {
            return;
        }

        for (MultipartFile file : newOrderFiles) {
            if (!MIME_TYPE_PDF.equals(file.getContentType())) {
                errors.rejectValue(file.getName(), file.getName(), "'application/pdf' files allowed only!");
            }

            if (file.getSize() > ALLOWED_SIZE) {
                errors.rejectValue(file.getName(), file.getName(), "File size allowed up to 3MB!");
            }
        }
    }

    @Override
    public boolean supports(Class<?> cls) {
        return NewOrderFilesDTO.class.equals(cls);
    }
}

最后是控制器:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseStatus;

import javax.validation.Valid;

import static org.springframework.http.HttpStatus.NO_CONTENT;
import static org.springframework.http.MediaType.MULTIPART_FORM_DATA_VALUE;
import static org.springframework.web.bind.annotation.RequestMethod.POST;

@Controller
class OrderController {

    private final NewOrderFilesValidator newOrderFilesValidator;

    @Autowired
    OrderController(NewOrderFilesValidator newOrderFilesValidator) {
        this.newOrderFilesValidator = newOrderFilesValidator;
    }

    @InitBinder("newOrderFiles")
    void initOrderFilesBinder(WebDataBinder binder) {
        binder.addValidators(newOrderFilesValidator);
    }

    @ResponseStatus(NO_CONTENT)
    @RequestMapping(value = ORDERS_PATH, method = POST, consumes = MULTIPART_FORM_DATA_VALUE)
    void createOrder(
            @Valid @ModelAttribute NewOrderFilesDTO newOrderFiles
    ) {

    }
}

通过上述配置,DTO 将由 spring 自动验证。