Проверка формы загрузки файла Spring multipart - PullRequest
5 голосов
/ 27 марта 2012

Я новичок в весне, и в настоящее время я борюсь со многими частями, необходимыми для получения сценария отправки / проверки составной формы с отображением ошибок в представлении.

Вот файлы, которые у меня сейчас есть:

resourceupload.jsp: представление, отображающее форму для загрузки файла.

<form:form method="post" action="resource/upload" enctype="mutlipart/form-data">
 <input name="name" type="text"/>
 <input name="file" type="file" />
 <input type="submit"/>
<form:errors path="file" cssClass="errors"/>
</form>

resourceuploadcontroller.java: контроллер, который обрабатывает отправку формы и (безуспешно) пытается отправить ошибки проверки файла обратно в представление:

@RequestMapping(method = RequestMethod.POST)
public String handleFormUpload( @RequestParam("file") MultipartFile file , @RequestParam("name") String name,Object command, Errors validationErrors){
..perform some stuff with the file content, checking things in the database, etc...
.. calling validationErrors.reject("file","the error") everytime something goes wrong...

return "redirect:upload"; // redirect to the form, that should display the error messages

Теперь, очевидно, что-то не так с этим подходом:

1 / Мне пришлось добавить фиктивный объект "command" перед параметром validationErrors, иначе spring выдаст мне ошибку. Это не совсем верно.

2 / После того, как я добавил этот параметр, редирект не передает ошибки представлению. Я попытался использовать @SessionAttribute ("file") при запуске контроллера, но безуспешно.

Если кто-нибудь может помочь ... Я посмотрел аннотацию @ResponseBody, но, похоже, она не предназначена для использования с представлениями ..

Ответы [ 4 ]

3 голосов
/ 27 марта 2012

Похоже, я нашел решение самостоятельно.

Во-первых, ссылка, которая мне очень помогла: http://www.ioncannon.net/programming/975/spring-3-file-upload-example/ а также Spring 3 MVC - форма: ошибки, не показывающие ошибки который показал хороший трюк для отображения всех ошибок, используя

<form:errors path="*"/>. 

Теперь список всех вещей, которые я изменил, чтобы заставить эту вещь работать:

1 / использовать «rejectValue» вместо «reject».

2 / вернуть представление напрямую вместо перенаправления.

3 / создать модель «UploadItem» со свойством CommonsMultipartFile

Итак, в целом мой метод управления стал

@RequestMapping(method = RequestMethod.POST)
public String handleFormUpload( @ModelAttribute("uploadItem") UploadItem uploadItem, BindingResult errors){
... use errors.rejectValue ... in case of errors (moving everything i could in a UploadItemValidator.validate function)
return "uploadform"

Надеюсь, это помогло.

2 голосов
/ 15 марта 2014

Вот очень простой способ сделать это:

ФормаBackingObject:

import org.springframework.web.multipart.commons.CommonsMultipartFile;

public class FileImport {

    CommonsMultipartFile  importFile;

    public CommonsMultipartFile getImportFile() {
        return importFile;
    }

    public void setImportFile(CommonsMultipartFile importFile) {
        this.importFile = importFile;
    }
}

Форма:

<sf:form method="POST" modelAttribute="fileImport" enctype="multipart/form-data" action="import">
    <table>
        <spring:hasBindErrors name="fileImport">
            <tr>
                <td colspan="2">
                    <sf:errors path="importFile" cssClass="error"/>
                </td>
            </tr>
        </spring:hasBindErrors>
        <tr>
            <th><label for="importFile">Import Workload:</label></th>
            <td><input name="importFile" type="file"></td>
        </tr>
    </table>
    <input type="submit" value="Import Application Data">
</sf:form>

И, наконец, метод ControllerClassMethod:

@RequestMapping(value={"/import"}, method=RequestMethod.POST)
public String importWorkload(
        FileImport fileImport, BindingResult bindResult,
        @RequestParam(value="importFile", required=true) MultipartFile importFile ){
    if( 0 == importFile.getSize() ){
        bindResult.rejectValue("importFile","fileImport.importFile");
    }

    if(bindResult.hasErrors()){
        return "admin";
    }
....
}

Легкий Писи!

Причина, по которой аннотация @NotNull не работает для файлов, заключается в том, что составной файл никогда не имеет значения null в объекте запроса. Но он может иметь 0 байтов. Вы можете потратить время на реализацию собственного валидатора, но почему?

1 голос
/ 20 января 2017

В Spring 4 вы можете реализовать валидатор файла, как показано ниже:

@Component
public class FileValidator implements Validator {

    @Override
    public boolean supports(Class<?> clazz) {
        return FileModel.class.isAssignableFrom(clazz);
    }

    @Override
    public void validate(Object target, Errors errors) {
        FileModel fileModel = (FileModel) target;

        if (fileModel.getFile() != null && fileModel.getFile().isEmpty()){
            errors.rejectValue("file", "file.empty");
        }
    }
}

, а затем добавить выше валидатор в контроллер загрузки, например так:

@Controller
@RequestMapping("/")
public class FileUploadController {

    @Autowired
    private FileValidator fileValidator;

    @ModelAttribute
    public FileModel fileModel(){
        return new FileModel();
    }

    @InitBinder
    protected void initBinderFileModel(WebDataBinder binder) {
        binder.setValidator(fileValidator);
    }

    @RequestMapping(method = RequestMethod.GET)
    public String single(){
        return "index";
    }

    @RequestMapping(method = RequestMethod.POST)
    public String handleFormUpload(@Valid FileModel fileModel,
                                   BindingResult result,
                                   RedirectAttributes redirectMap) throws IOException {

        if (result.hasErrors()){
            return "index";
        }

        MultipartFile file = fileModel.getFile();
        InputStream in = file.getInputStream();
        File destination = new File("/tmp/" + file.getOriginalFilename());
        FileUtils.copyInputStreamToFile(in, destination);

        redirectMap.addFlashAttribute("filename", file.getOriginalFilename());
        return "redirect:success";
    }
}

Эта реализация помогаетВаш код более понятный и более читаемый.Я нашел его из учебника Пример проверки загрузки файла Spring MVC

1 голос
/ 15 апреля 2012

Я не думаю, что этот подход полностью охватывает Spring, но он работает, прост и использует простую HTML-форму и один метод в контроллере:

HTML-файл, чтобы сделать сообщение (сохранить как JSPили html, ваш вызов)

<html>
  <head>
    <title>File Upload Example</title>
  </head>
  <body>
    <form action="save_uploaded_file.html" method="post" enctype="multipart/form-data">
        Choose a file to upload to the server:
        <input name="myFile" type="file"/><br/>
      <p>
        <input type="submit"/>
        <input type="reset"/>
      </p>
    </form>
  </body>
</html>

в вашем контроллере, используйте следующий метод:

@RequestMapping("/save_uploaded_file")
public String testUpload(HttpServletRequest request) throws Exception
{
    // get the file from the request
    MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
    MultipartFile multipartFile = multipartRequest.getFile("myFile");

    // Note: Make sure this output folder already exists!
    // The following saves the file to a folder on your hard drive.
    String outputFilename = "/tmp/uploaded_files/file2.txt";
    OutputStream out = new FileOutputStream(outputFilename);
    IOUtils.copy(multipartFile.getInputStream(), out);

    return "/save_uploaded_file";
}

Чтобы получить файлы большего размера для загрузки (более 40 КБ), вам может потребоваться указатьследующее в конфигурации весеннего сервлета .... Я поместил несколько больших #, чтобы убедиться, что это работает, но, конечно, если нужно, добавьте "реальные" числа.

<!-- Configure the multipart resolver -->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
    <!-- one of the properties available; the maximum file size in bytes -->
    <property name="maxUploadSize" value="500000000"/>
    <property name="maxInMemorySize" value="500000000" />
</bean>

Примечаниечто для загрузки файлов в Spring используется Apache Commons FileUpload под обложками.Вам нужно будет загрузить это и включить его в свое приложение.Это, в свою очередь, также требует Apache Commons IO , так что вам это тоже понадобится.(цитата из здесь )

...