精通 Spring Boot 系列 06
閱讀全文,約 13?分鐘

這是江帥帥的第006篇原創(chuàng)
Spring Boot 文件的上傳下載
說真的,在 Spring Boot 實現(xiàn)文件下載,真的是方便到讓我顫抖。Java 中實現(xiàn)文件上傳可以用兩個組件:CommonMultipartResolver 和 StandardServletMultipartResolver。
Spring Boot 在 web 模塊中集成了 Spring MVC ,文件上傳這塊兒的支持是可以通過即插即用的 MultipartResolver 實現(xiàn)類:CommonMultipartResolver。如果用它,則需要使用 commons-fileupload 組件來處理。
Spring Boot 提供的文件上傳自動化配置類是 MultipartAutoConfiguration 中默認使用了 StandardServletMultipartResolver,在上傳文件甚至能夠做到零配置。
1. 單文件上傳
1)添加 fileUpload.html 文件
在上傳頁面的表單中,添加一個 type 為 file 的控件,用來選擇需要上傳的圖片文件。上傳的接口是“/upload”,另外 method 要設置為“post”,還有 enctype 要設置為“multipart/form-data”,代碼具體如下:
<html?lang="en">
<head>
????<meta?charset="UTF-8">
????<title>uploadtitle>
head>
<body>
<form?action="/upload"?method="post"?enctype="multipart/form-data">
????<p><input?type="file"?name="upload"?value="選一張圖片">p>
????<p><input?type="submit"?value="開始上傳">p>
form>
body>
html>
2)添加 FileUploadController 文件
首先,設置我們的文件上傳路徑為項目運行目錄下的 upload 文件夾。然后,我們用 MultipartFile 來綁定上傳的文件,使用 transferTo() 方法可以非常方便實現(xiàn)文件存儲到磁盤當中。具體實現(xiàn)代碼如下:
@PostMapping("/upload")
public?String?upload(HttpServletRequest?req,?MultipartFile?uploadFile)?{
????String?path?=?req.getSession().getServletContext().getRealPath("/upload/");
????File?folder?=?new?File(path);
????if?(!folder.isDirectory())?{
????????folder.mkdirs();
????}
????String?oName?=?uploadFile.getOriginalFilename();
????String?nName?=?UUID.randomUUID().toString()?+?oName.substring(oName.lastIndexOf("."),?oName.length());
????try?{
????????uploadFile.transferTo(new?File(folder?+?File.separator?+?nName));
????????String?filePath?=?req.getScheme()?+?"://"?+?req.getServerName()?+?":"?+?req.getServerPort()?+?"/upload/"?+?nName;
????????return?"ok";
????}?catch?(IOException?ex)?{
????????ex.printStackTrace();
????}
????return?"error";
}
地址欄中,輸入 http://localhost:8080/fileUpload.html 選擇文件上傳,具體運行效果如下:


2. 采用對象方式來上傳文件
很多時候的上傳操作,也都會把文件作為對象的屬性進行保存,具體如何實現(xiàn)?下面通過注冊頁面,填寫用戶的相關信息,然后點擊注冊來上傳 User 對象。
1)添加 fileUpload2.html 文件
通過一個表單,來收集用戶的具體信息,然后點擊“注冊用戶”按鈕即可提交 /register 注冊請求。代碼具體如下:
<body>
????<form?action="/register"?method="post"?enctype="multipart/form-data">
????????<p>用戶名:<input?type="text"?name="username">p>
????????<p>密碼:<input?type="text"?name="password">p>
????????<p>頭像:<input?type="file"?name="pic">p>
????????<p><input?type="submit"?value="注冊用戶">p>
????form>
body>
2)添加 User 類
User 類主要是用來封裝用戶信息的,其中 MultipartFile 類型的 pic 是用來接收上傳的圖像文件。
public?class?User?{
????private?String?username;
????private?String?password;
????private?MultipartFile?pic;
????//?getter?和?setter?方法
}
3)添加 userRegister() 方法
在 userRegister() 方法形參列表中,使用 @ModelAttribute 注解將表單提交的數(shù)據(jù)綁定到 User 對象中,其中圖片會保存到 User 的 pic 屬性中,然后轉換為 Multipart 類型。文件上傳成功之后,所有的用戶信息都保存到 model 當中。
@Controller
public?class?FileUploadController?{
????@PostMapping("/register")
????public?String?userRegister(HttpServletRequest?req,?@ModelAttribute?User?user,?Model?model)?throws?Exception?{
????????if?(!user.getPic().isEmpty())?{
????????????String?picPath?=?req.getServletContext().getRealPath("/upload/");
????????????String?picName?=?user.getPic().getOriginalFilename();
????????????File?filePath?=?new?File(picPath,?picName);
????????????if?(!filePath.getParentFile().exists()){
????????????????filePath.getParentFile().mkdirs();
????????????}
????????????user.getPic().transferTo(new?File(picPath?+?File.separator?+?picName));
????????????model.addAttribute("user",?user);
????????????return?"userMsg";
????????}?else?{
????????????return?"error";
????????}
????}
}
3)在 templates 目錄中,添加 userMsg.html 文件
<body>
????<table>
????????<tr>
????????????<td><img?th:src="@{'upload/'+${user.pic.originalFilename}}"?height="100"/>td>
????????????<td?th:text="${user.username}">用戶名td>
????????tr>
????table>
body>
運行效果,具體如下:

3. 多文件上傳
1)添加 fileUpload2.html 頁面
<form?action="/uploadFiles"?method="post"?enctype="multipart/form-data">
????<p>選第一張圖片:<input?type="file"?name="uploadFiles">p>
????<p>選第二張圖片:<input?type="file"?name="uploadFiles">p>
????<p>選第三張圖片:<input?type="file"?name="uploadFiles">p>
????<p><input?type="submit"?value="開始上傳">p>
form>
body>
2)添加 uploadFiles() 方法
@PostMapping("/uploadFiles")
public?String?uploadFiles(MultipartFile[]?uploadFiles,?HttpServletRequest?req)?{
????String?path?=?req.getSession().getServletContext().getRealPath("/upload/");
????File?folder?=?new?File(path);
????if?(!folder.isDirectory())?{
????????folder.mkdirs();
????}
????if?(null?!=?uploadFiles?&&?uploadFiles.length?>?0)?{
????????for?(MultipartFile?uploadFile?:?uploadFiles)?{
????????????String?oName?=?uploadFile.getOriginalFilename();
????????????String?nName?=?UUID.randomUUID().toString()?+?oName.substring(oName.lastIndexOf("."),?oName.length());
????????????try?{
????????????????uploadFile.transferTo(new?File(folder,?nName));
????????????????return?"ok";
????????????}?catch?(IOException?ex)?{
????????????????ex.printStackTrace();
????????????}
????????}
????}
????return?"error";
}
運行結果,具體如下:

4. 文件下載
1)編輯 userMsg.html 頁面
<table>
????<tr>
????????<td><img?th:src="@{'upload/'+${user.pic.originalFilename}}"?height="100"/>td>
????????<td?th:text="${user.username}">用戶名td>
????????<td><a?th:href="@{download(pic=${user.pic.originalFilename?})}">下載頭像a>td>
????tr>
table>
2)添加 downloadPic() 方法
這里使用了 ResponseEntity 類型,就能定義返回的 HttpHeaders、BodyBuilder 和 HttpStatus,然后返回客戶端下載。
@RequestMapping(value="/download")
public?ResponseEntity<byte[]>?downloadPic(HttpServletRequest?request,?@RequestParam("pic")?String?filename,?@RequestHeader("User-Agent")?String?userAgent,?Model?model)throws?Exception{
????String?path?=?request.getServletContext().getRealPath(
????????"/upload/");
????File?file?=?new?File(path?+?File.separator?+?filename);
????BodyBuilder?builder?=?ResponseEntity.ok();
????builder.contentLength(file.length());
????//?二進制流數(shù)據(jù)
????builder.contentType(MediaType.APPLICATION_OCTET_STREAM);
????//?解碼
????filename?=?URLEncoder.encode(filename,?"UTF-8");
????if?(userAgent.indexOf("MSIE")?>?0)?{
????????//?IE
????????builder.header("Content-Disposition",?"attachment;?filename="?+?filename);
????}?else?{
????????//?FireFox、Chrome
????????builder.header("Content-Disposition",?"attachment;?filename*=UTF-8''"?+?filename);
????}
????return?builder.body(FileUtils.readFileToByteArray(file));
}
運行效果,具體如下:


來源公眾號:江帥帥(ID:NXJSS666)
?--END--
? 推薦
公眾號ID|javabaiwen
小編微信|619531440
每天分享技術干貨
視頻 | 電子書 | 面試題?|?開發(fā)經(jīng)驗

