2015-12-20 3 views
1

Я пытаюсь создать приложение Spring Boot, которое загружает файлы и сохраняет их в HttpSession для будущего использования (только для образовательной цели). У меня проблема с файлами 'MultipartFile getSize(). Он возвращает ненулевые значения в методе обработчика POST и возвращает нули каждый раз, когда я получаю их из HttpSession в методе обработчика GET. В то же время getOriginalFileName() возвращает правильные имена. Поэтому моя таблица «Загруженные файлы:» отображает имена файлов правильно, но размеры - нули.Хранение MultipartFile в HttpSession

Возможно, я концептуально неправильно пытаюсь сохранить MultipartFile в HttpSession?

Как шаблоны я использую Thymeleaf.

Вот шаблон:

<!DOCTYPE html> 
<html xmlns="http://www.w3.org/1999/xhtml" 
     xmlns:th="http://www.thymeleaf.org" 
     lang="en"> 
<head> 
    <title>File Uploader</title> 
</head> 
<body> 
<form method="POST" action="upload" enctype="multipart/form-data"> 
    <input type="file" name="files" id="files" multiple="multiple"/> <br/> 
    <input type="submit" value="Upload" name="upload" id="upload"/> 
    <input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}"/> 
</form> 
<h3>Loaded files:</h3> 
<table border="1px"> 
    <thead> 
    <tr> 
     <td>File name</td> 
     <td>Size</td> 
    </tr> 
    </thead> 
    <tr th:each="file : ${uploadedFiles}"> 
     <td th:text="${file.originalFilename}"/> 
     <td th:text="${file.size}"/> 
    </tr> 
</table> 
<form method="POST" action="confirm"> 
    <input type="submit" value="Confirm" name="confirm" id="confirm"/> 
    <input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}"/> 
</form> 
</body> 
</html> 

Вот контроллер:

@Controller 
public class IndexController { 
    @RequestMapping("/") 
    public String index(Model model, HttpSession httpSession) { 
     List<MultipartFile> uploadedFiles = (List<MultipartFile>) httpSession.getAttribute("uploadedFiles"); 
     model.addAttribute("uploadedFiles", uploadedFiles); 
     return "index"; 
    } 

    @RequestMapping(value = "upload", method = RequestMethod.POST) 
    public String index(@RequestParam("files") MultipartFile[] files, HttpSession httpSession) { 
     List<MultipartFile> uploadedFiles = (List<MultipartFile>) httpSession.getAttribute("uploadedFiles"); 
     if (uploadedFiles != null) { 
      uploadedFiles.addAll(Arrays.asList(files)); 
     } else { 
      uploadedFiles = Arrays.asList(files); 
     } 
     httpSession.setAttribute("uploadedFiles", uploadedFiles); 
     return "redirect:"; 
    } 
} 

ответ

4

После некоторого исследования я обнаружил, что MultipartFile существует во временном каталоге только тогда, когда Tomcat обрабатывает запрос. Сразу после ответа удаляет файл. Вот почему размер равен нулю. Эти данные можно хранить в памяти или в БД или в другом месте, используя пользовательскую структуру.

Вот пример:

public class UploadedFile { 
    private final String originalFilename; 
    private final byte[] data; 

    public UploadedFile(String fileName, byte[] data) { 
     this.originalFilename = fileName; 
     this.data = data.clone(); 
    } 

    public String getOriginalFilename() { 
     return originalFilename; 
    } 

    public byte[] getData() { 
     return data.clone(); 
    } 

    public int getSize() { 
     return data.length; 
    } 
} 

В случае в памяти хранения класса MultipartFile можно было бы использовать. Если файл не хранится на жестком диске, он существует в памяти, если у вас есть ссылка на него.

Вот пример application.properties файла:

multipart.file-size-threshold=10Mb 
multipart.max-file-size=10Mb 
multipart.max-request-size=10Mb 

multipart.file величину порога силы все загруженные файлы до 10 Мб, чтобы быть сохранены в памяти, а не жесткий диск. По умолчанию он равен 0, и все файлы хранятся на жестком диске.

Также я обнаружил, что использование HttpSession не является изящным решением. @SessionAttributes аннотация вместе с Модель делает это решение довольно ясным.

Вот обновленный контроллер:

@Controller 
@SessionAttributes(value = {"uploadedFiles"}) 
public class IndexController { 
    @ModelAttribute("uploadedFiles") 
    public List<UploadedFile> initUploadedFiles() { 
     return new ArrayList<>(); 
    } 

    @RequestMapping("/") 
    public String index() { 
     return "index"; 
    } 

    @RequestMapping(value = "upload", method = RequestMethod.POST) 
    public String index(Model model, @RequestParam MultipartFile[] files, @ModelAttribute("uploadedFiles") List<UploadedFile> uploadedFiles) { 
     for (MultipartFile file : files) { 
      try { 
       uploadedFiles.add(new UploadedFile(file.getOriginalFilename(), file.getBytes())); 
      } catch (IOException e) { 
       throw new RuntimeException("Can't read file " + file.getOriginalFilename(), e); 
      } 
     } 
     model.addAttribute("uploadedFiles", uploadedFiles); 
     return "redirect:"; 
    } 
} 
+0

это было очень полезно для me..thanks приятеля –

Смежные вопросы