文件上傳
SpringBoot打包? 上傳文件和下載文件是Java Web中常見的一種操作,文件上傳主要是將文件通過IO流傳輸到服務器的某一個文件夾下。
導入依賴
在pom.xml中添加上spring-boot-starter-web和spring-boot-starter-thymeleaf的依賴
<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-thymeleaf</artifactId></dependency> </dependencies>
配置文件
默認情況下SPring Boot無需做任何配置也能實現文件上傳的功能,但有可能因默認配置不符而導致文件上傳失敗問題,所以了解相關配置信息更有助于我們對問題的定位和修復。
spring:#禁用thymeleaf緩存thymeleaf:cache: falseservlet:multipart:#是否支持批量上傳(默認true)enabled: true#上傳文件的臨時目錄(一般不用修改)location:max-file-size: 1048576#上傳請求最大為10M(默認10M)max-request-size: 10485760#文件大小閥值,當大于這個閥值時將寫入到磁盤,否則存在內存中(默認值0 一般不用修改)file-size-threshold: 0#判斷是否要延遲解析文件(相當于懶加載 一般不用修改)resolve-lazily: false
如果只允許1M以下的文件,當超出該范圍則會拋出以下錯誤
org.apache.tomcat.util.http.fileupload.FileUploadBase$SizeLimitExceededException:
the request was rejected because its size (20738021) exceeds the configured maximum (10485760)
?
上傳頁面
在src/main/resources下新建static,在static中新建一個index.html的模板文件,實現單文件上傳、多文件上傳、BASE64編碼三種上傳方式,其中BASE64的方式在對Android/IOS/H5等方面還是不錯的
<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><title>文件上傳</title> </head> <body><h2>單一文件上傳示例</h2> <div><form method="POST" enctype="multipart/form-data" action="/uploads/upload1"><p>文件1:<input type="file" name="file"/><input type="submit" value="上傳"/></p></form> </div><hr/> <h2>批量文件上傳示例</h2><div><form method="POST" enctype="multipart/form-data" action="/uploads/upload2"><p>文件1:<input type="file" name="file"/></p><p>文件2:<input type="file" name="file"/></p><p><input type="submit" value="上傳"/></p></form> </div><hr/> <h2>Base64文件上傳</h2> <div><form method="POST" action="/uploads/upload3"><p>BASE64編碼:<textarea name="base64" rows="10" cols="80"></textarea><input type="submit" value="上傳"/></p></form> </div></body> </html>
控制層
創建一個FileUploadController,其中@GetMapping的方式用來跳轉index.html頁面,而@PostMapping相關方法則是對應的單文件上傳、多文件上傳、BASE64編碼三種方式
@Request("file")此處的file對應的就是html中的name="file"的input標簽,而將文件真正寫入的還是借助的commons-io中的FileUtils.copyInputStreamToFile(inputStream,file)
package com.spring.boot.controller;import org.springframework.stereotype.Controller; import org.springframework.util.Base64Utils; import org.springframework.util.FileCopyUtils; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.multipart.MultipartFile;import javax.servlet.http.HttpServletRequest; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map;@Controller @RequestMapping("/uploads") public class FileUploadController {@PostMapping("/upload1")@ResponseBodypublic Map<String,String> upload1(@RequestParam("file")MultipartFile imgFile,HttpServletRequest request) throws IOException {// 獲取文件名String fileName = imgFile.getOriginalFilename();// 獲取圖片后綴String extName = fileName.substring(fileName.lastIndexOf("."));if(extName.equals(".jpg")){// 自定義的文件名稱String trueFileName=String.valueOf(System.currentTimeMillis())+fileName;// 設置存放圖片文件的路徑String path="/Users/baidawei/Downloads/imgUpload/" +trueFileName;// 開始上傳imgFile.transferTo(new File(path));}Map<String, String> result = new HashMap<>(16);result.put("contentType", imgFile.getContentType());result.put("fileName", imgFile.getOriginalFilename());result.put("fileSize", imgFile.getSize() + "");return result;}@PostMapping("/upload2")@ResponseBodypublic List<Map<String,String>> upload2(@RequestParam("file") MultipartFile [] files) throws IOException {if(files ==null || files.length == 0){return null;}List<Map<String,String>> results = new ArrayList<>();for(MultipartFile file : files){String path="/Users/baidawei/Downloads/imgUpload/" + file.getOriginalFilename();file.transferTo(new File(path));Map<String, String> map = new HashMap<>(16);map.put("contentType", file.getContentType());map.put("fileName", file.getOriginalFilename());map.put("fileSize", file.getSize() + "");results.add(map);}return results;}@PostMapping("/upload3")@ResponseBodypublic void upload3(String base64) throws IOException {// TODO BASE64 方式的 格式和名字需要自己控制(如 png 圖片編碼后前綴就會是 data:image/png;base64,)final File tempFile = new File("/Users/baidawei/Downloads/imgUpload/test.jpg");// TODO 防止有的傳了 data:image/png;base64, 有的沒傳的情況String[] d = base64.split("base64,");final byte[] bytes = Base64Utils.decodeFromString(d.length > 1 ? d[1] : d[0]);FileCopyUtils.copy(bytes,tempFile);}}
?
啟動項目進行測試:
http://localhost:8088/
上傳單個返回:
{"fileName":"sunwukong.jpg","fileSize":"199556","contentType":"image/jpeg"}
上傳多個圖片 返回:
[{"fileName":"獅子頭.jpg","fileSize":"187554","contentType":"image/jpeg"},{"fileName":"mh1.jpg","fileSize":"260842","contentType":"image/jpeg"}]
Base64編碼轉換地址:http://base64.xpcha.com/pic.html
需要先把圖片轉換為base64編碼后 再上傳
?