ZeA*_*L0T 3 spring spring-mvc thymeleaf spring-boot
我正在尝试创建一个Spring Boot应用程序,它上传文件并将它们存储在HttpSession中以备将来使用(仅用于教育目的).我的文件' MultipartFile getSize()有问题.它在POST处理程序方法中返回非零值,并且每次从GET处理程序方法中的HttpSession获取它时返回零.同时getOriginalFileName()返回正确的名称.所以我的"已加载文件:"表正确显示文件名,但大小为零.
也许我在概念上错误地尝试将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>
Run Code Online (Sandbox Code Playgroud)
这是一个控制器:
@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:";
}
}
Run Code Online (Sandbox Code Playgroud)
经过一些调查后,我发现只有在Tomcat处理请求时,MultipartFile才存在于临时目录中.在响应后它删除文件.这就是尺寸为零的原因.可以使用自定义结构将此数据存储在内存或DB或其他位置.
这是一个例子:
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;
}
}
Run Code Online (Sandbox Code Playgroud)
在内存存储的情况下,可以使用MultipartFile类.如果文件没有存储在硬盘上,只要你有参考文件,它就存在于内存中.
以下是application.properties文件的示例:
multipart.file-size-threshold=10Mb
multipart.max-file-size=10Mb
multipart.max-request-size=10Mb
Run Code Online (Sandbox Code Playgroud)
multipart.file-size-threshold强制所有上传的文件最多10MB存储在内存而不是HDD中.默认情况下,它等于0,所有文件都存储在HDD上.
我还发现使用HttpSession不是一个优雅的决定. @SessionAttributes注释与Model一起使这个解决方案相当清晰.
这是更新的控制器:
@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:";
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1239 次 |
| 最近记录: |