文件上傳
文件上傳是Web開發非常重要的操作
結合SpringBoot實現文件上傳操作
1、基礎上傳
SpringBoot採用FileUpload組件實現上傳處理,在控制器中可以使用MultipartFile類進行接收。
FileUpload上傳 MultipartFile接收
1、建立上傳控制器UploadController,利用MultipartFile將上傳文件保存在本地磁盤。
一個上傳文件的接口,訪問接口選擇把要上傳的文件利用MultipartFile上傳保存在本地磁盤中。
@Controller
public class UploadController {
//訪問http://localhost//upload_pre 顯示upload.html頁面
@GetMapping("/upload_pre")
public String uploadPre() { // 通過model可以實現內容的傳遞
return "upload";
}
//upload
@PostMapping("/upload")
@ResponseBody
public Object upload(String name, MultipartFile photo) throws Exception {
Map<String, Object> map = new HashMap<String, Object>();
if (photo != null) { // 現在有文件上傳
//姓名
map.put("name-param", name);
//文件名
map.put("photo-name", photo.getName());
//文件類型 content-type: "image/png",
map.put("content-type", photo.getContentType());
//文件大小
map.put("photo-size", photo.getSize());
//eg: UUID + . + png
String fileName = UUID.randomUUID() + "."
+ photo.getContentType().substring(
photo.getContentType().lastIndexOf("/") + 1); // 創建文件名稱
//文件路徑 位置 + 文件名
String filePath = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
.getRequest().getServletContext().getRealPath("/") + fileName;
//文件路徑
map.put("photo-path", filePath);
File saveFile = new File(filePath);
photo.transferTo(saveFile); // 文件保存
return map;
} else {
return "nothing";
}
}
}
2、建立src/main/view/templates/upload.html頁面
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>文件上傳</title>
<script type="text/javascript" th:src="@{/js/main.js}"></script>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
</head>
<body>
<form th:action="@{/upload}" method="post" enctype="multipart/form-data">
姓名:<input type="text" name="name"/><br/>
照片:<input type="file" name="photo"/><br/>
<input type="submit" value="上傳"/>
</form>
</body>
</html>
執行
upload.html頁面表單填入姓名和選擇圖片點擊上傳向upload接口傳遞了姓名(文本)和圖片(二進制數據)兩個數據信息。控制器接收到此請求信息後,返回JSON格式信息
{
photo-size: 23902,
content-type: "image/png",
photo-path: "C:\Windows\Temp\tomcat-docbase.6786357466203986968.80\2a220798-ecbe-4fae-a1c9-485d75d7dfe1.png",
photo-name: "photo",
name-param: "liuawen"
}
2、上傳文件限制
在實際項目開發中,需要對用戶上傳文件的大小進行限制,這樣纔可以保證服務器的資源不被浪費。 配置yml實現上傳限制
1、修改application.yml配置文件,增加上傳限制。
application.yml
spring:
http:
multipart:
enabled: true # 啓用http上傳
max-file-size: 10MB # 設置支持的單個上傳文件的大小限制
max-request-size: 20MB # 設置最大的請求的文件大小,設置總體大小請求
file-size-threshold: 512KB # 當上傳文件達到指定配置量的時候會將文件內容寫入磁盤
location: / # 設置上傳的臨時目錄
2、對於上傳限制,也可以利用Bean實現同樣的效果。·
cn.liuawen.config UploadConfig.java
@Configuration
public class UploadConfig {
@Bean
public MultipartConfigElement getMultipartConfig() {
MultipartConfigFactory config = new MultipartConfigFactory() ;
config.setMaxFileSize("100KB"); // 設置上傳文件的單個大小限制
config.setMaxRequestSize("20MB"); // 設置總的上傳的大小限制
config.setLocation("/"); // 設置臨時保存目錄
return config.createMultipartConfig() ; // 創建一個上傳配置
}
}
設置上傳文件的單個大小限制
爲了測試我把上傳文件的單個大小限制設置小了點 看測試是否有異常
上傳了個195KB的
http://localhost/upload
上傳出錯後頁面執行的效果
錯誤路徑:http://localhost/upload
錯誤信息:Could not parse multipart servlet request; nested exception is java.lang.IllegalStateException: org.apache.tomcat.util.http.fileupload.FileUploadBase$FileSizeLimitExceededException: The field photo exceeds its maximum permitted size of 102400 bytes.
錯誤 圖片太大了,用戶上傳的內容超過了配置的限制,全局異常處理 。
3、上傳多個文件
如果要進行多個文件的上傳,需要通過MultipartHttpServletRequest進行文件接收。
1、修改upload.html頁面,定義多個文件上傳控件。
upload.html
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>SpringBoot多文件上傳</title>
<script type="text/javascript" th:src="@{/js/main.js}"></script>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
</head>
<body>
<form th:action="@{/upload}" method="post" enctype="multipart/form-data">
姓名:<input type="text" name="name"/><br/>
<!-- 選擇多個文件上傳 這裏是一個個的呀-->
照片1:<input type="file" name="photo"/><br/>
照片2:<input type="file" name="photo"/><br/>
照片3:<input type="file" name="photo"/><br/>
<input type="submit" value="上傳"/>
</form>
</body>
</html>
2、修改UploadController控制器,實現多個文件上傳。
@Controller
public class UploadController {
@GetMapping("/upload_pre")
public String uploadPre() { // 通過model可以實現內容的傳遞
return "upload";
}
@PostMapping("/upload")
@ResponseBody
public Object upload(String name, HttpServletRequest request) {
List<String> result = new ArrayList<String>() ;
//多個文件上傳 就只是簡單的多文件上傳保存在本地的磁盤
if (request instanceof MultipartHttpServletRequest) {
MultipartHttpServletRequest mrequest = (MultipartHttpServletRequest) request;
//<input type="file" name="photo"/>
List<MultipartFile> files = mrequest.getFiles("photo");
Iterator<MultipartFile> iter = files.iterator();
while (iter.hasNext()) {
MultipartFile photo = iter.next() ; // 取出每一個上傳文件
try {
result.add(this.saveFile(photo)) ; // 保存上傳信息
} catch (Exception e) {
e.printStackTrace();
}
}
}
return result ;
}
/**
* 文件保存處理
* @param file 上傳文件
* @return 文件保存路徑
* @throws Exception 上傳異常
*/
public String saveFile(MultipartFile file) throws Exception {
String path = "nothing" ;
if (file != null) { // 有文件上傳
if (file.getSize() > 0) {
String fileName = UUID.randomUUID() + "."
+ file.getContentType().substring(
file.getContentType().lastIndexOf("/") + 1); // 創建文件名稱
path = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
.getRequest().getServletContext().getRealPath("/") + fileName;
File saveFile = new File(path) ;
file.transferTo(saveFile); // 文件保存
}
}
return path ;
}
}
3、測試
http://localhost/upload_pre
http://localhost/upload
[
"C:\Windows\Temp\tomcat-docbase.1489099008397591870.80\c97e9432-4716-4ef8-93d0-d18f3b4ab74d.png",
"C:\Windows\Temp\tomcat-docbase.1489099008397591870.80\09bab86d-44bd-426e-8d5c-9d7c17929ae7.png",
"C:\Windows\Temp\tomcat-docbase.1489099008397591870.80\5d30e2de-f83a-4113-8c96-69b3e92de086.png"
]
爲了方便文件上傳,就簡單在控制器類中定義了一個saveFile()方法,以進行文件的保存,同時利用此方法返回了上傳文件的保存路徑。
這裏的保存上傳圖片都是保存到本地磁盤的,
假的上傳😂
實際開發不是這樣的,在當今的項目開發中,最流行的設計理念是高可用、高併發、分佈式設計,所以在實際項目中需要搭建專門的圖片服務器進行上傳資源的保存。
圖片服務器集羣
4、參考資料
簡單記錄
1、名師講壇:Java微服務架構實戰(SpringBoot+SpringCloud+Docker+RabbitMQ)- 李興華