一、Java web 應用開發完成後若是是導入外置的 Tomcat 的 webapps 目錄的話,那麼上傳的文件能夠直接的放在應用的 web 目錄下去就行了,瀏覽器能夠很方便的進行訪問。html
二、Spring Boot 默認使用嵌入式 Tomcat ,未來打包成可執行 Jar 文件進行部署,顯然打成 jar 包後,總不可能再將上傳的文件放在 resources 目錄下去了。前端
三、Spring Boot 因而提供了 url 地址匹配本地虛擬路徑的功能:java
1)上傳文件到服務器,服務器將文件保存到了本地,如:E:\wmx\uploadFiles\222.png
2)用戶訪問應該是服務器地址,如:http://localhost:9393/fileServer/uploadFiles/222.png
3)因而經過配置資源映射,使 url 中的 /uploadFiles/ 映射到本地的 E:\wmx\uploadFiles\ 便可,E:\wmx\uploadFiles 則爲虛擬路徑。
一、Java JDK 1.8 + Spring Boot 2.1.3 新建 web 項目,spring boot 版本不一樣,可能略有差別。web
二、spring boot 的 web 組件中的 org.springframework:spring-web 已經集成了文件上傳功能,無需再導入之前的 commons-io、以及 commons-fileupload 了,使用方式和以前的 commons-fileupload 徹底同樣。spring
pom.xml
一、pom.xml 內容以下,爲了頁面寫起來方便,使用了 Thymeleaf 模板引擎,java web 應用,天然須要導入 web 組件。數據庫
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.3.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>www.wmx.com</groupId> <artifactId>fileServer</artifactId> <version>0.0.1-SNAPSHOT</version> <name>fileServer</name> <description>Demo project for Spring Boot</description> <properties> <java.version>1.8</java.version> </properties> <dependencies> <!-- thymeleaf 模板引擎--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> <!-- web 組件--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- spring boot 測試組件--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
一、應用全局配置文件內容以下:apache
#配置服務器
server:
port: 9393 #服務器端口
servlet:
context-path: /fileServer #應用上下文路徑
spring:
servlet:
multipart: #配置文件上傳
max-file-size: 1000MB #設置上傳的單個文件最大值,單位能夠是 MB、KB,默認爲 1MB
max-request-size: 1024MB #設置多文件上傳時,單次內多個文件的總量的最大值,單位能夠是 MB、KB,默認爲 10 M
uploadFile:
location: E:/wmx/uploadFiles #自定義上傳文件本地保存路徑
二、文件上傳官網介紹:Handling Multipart File Uploads,除了配置上面的單個文件最大值已經單次上傳總量之外,官網還提供了以下配置:瀏覽器
# MULTIPART (MultipartProperties)
spring.servlet.multipart.enabled=true # Whether to enable support of multipart uploads.
spring.servlet.multipart.file-size-threshold=0B # Threshold after which files are written to disk.
spring.servlet.multipart.location= # Intermediate location of uploaded files.
spring.servlet.multipart.max-file-size=1MB # Max file size.
spring.servlet.multipart.max-request-size=10MB # Max request size.
spring.servlet.multipart.resolve-lazily=false # Whether to resolve the multipart request lazily at the time of file or parameter access.
三、上傳文件存放的目錄,不該該寫死在代碼中,因此上面提供了在配置文件中配置 uploadFile.location 屬性,未來類中使用 @Value 取值便可。服務器
UploadFileController
一、文件上傳後臺控制檯層代碼以下,後期實現 虛擬路徑映射本地路徑會修改。app
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
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;
/**
* Created by Administrator on 2019/3/17 0017.
*/
@Controller
public class UploadFileController {
@Value("${uploadFile.location}")
private String uploadFileLocation;//上傳文件保存的本地目錄,使用@Value獲取全局配置文件中配置的屬性值
/**
* 文件上傳,由於只是演示,因此使用 @ResponseBody 將結果直接返回給頁面
*
* @param multipartFile
* @param request
* @return
* @throws IOException
*/
@PostMapping("uploadFile")
@ResponseBody
public String uploadFile(MultipartFile multipartFile, HttpServletRequest request) throws IOException {
if (multipartFile == null || multipartFile.isEmpty()) {
return "上傳文件爲空...";
}
//basePath拼接完成後,形如:http://192.168.1.20:8080/fileServer
String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + request.getContextPath();
System.out.println("basePath=" + basePath);
String fileName = multipartFile.getOriginalFilename();
File saveFile = new File(uploadFileLocation, fileName);
System.out.println("文件保存成功:" + saveFile.getPath());
multipartFile.transferTo(saveFile);//文件保存
return saveFile.getPath().toString();
}
}
一、前端文件上傳 form 表單以下:
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title>文件服務器</title> </head> <body> <form id="uploadForm" method="post" action="http://localhost:9393/fileServer/uploadFile" enctype="multipart/form-data"> <input type="file" name="multipartFile" style="font-size: 20px"/><br> <input type="submit" id="uploadButton" value="上傳" style="font-size: 30px"> </form> </body> </html>
url 映射虛擬路徑
一、使用資源映射虛擬路徑很簡單,使用 WebMvcConfigurer 擴展配置便可,不熟悉的能夠參考《Web 項目 tiger 之3 WebMvcConfigurer 實現登陸與攔截、過濾靜態資源》中的「自定義資源映射」部分。
application.yml
一、首先修改一下 application.yml 文件:
#配置服務器
server:
port: 9393 #服務器端口
servlet:
context-path: /fileServer #應用上下文路徑
spring:
servlet:
multipart: #配置文件上傳
max-file-size: 1000MB #設置上傳的單個文件最大值,單位能夠是 MB、KB,默認爲 1MB
max-request-size: 1024MB #設置多文件上傳時,單次內多個文件的總量的最大值,單位能夠是 MB、KB,默認爲 10 M
uploadFile:
resourceHandler: /uploadFiles/** #請求 url 中的資源映射
location: E:/wmx/uploadFiles/ #自定義上傳文件本地保存路徑
一、再擴展 webMvc 配置,設置資源映射:
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* WebMvc 擴展配置類,應用一啓動,本類就會執行
* Created by Administrator on 2019/3/17 0017.
*/
@Configuration
public class MyWebMvcConfigurer implements WebMvcConfigurer {
@Value("${uploadFile.resourceHandler}")
private String resourceHandler;//請求 url 中的資源映射,不推薦寫死在代碼中,最好提供可配置,如 /uploadFiles/**
@Value("${uploadFile.location}")
private String location;//上傳文件保存的本地目錄,使用@Value獲取全局配置文件中配置的屬性值,如 E:/wmx/uploadFiles/
/**
* 配置靜態資源映射
*
* @param registry
*/
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
//就是說 url 中出現 resourceHandler 匹配時,則映射到 location 中去,location 至關於虛擬路徑
//映射本地文件時,開頭必須是 file:/// 開頭,表示協議
registry.addResourceHandler(resourceHandler).addResourceLocations("file:///" + location);
}
}
UploadFileController
一、改寫一下控制器。特別提醒一句:實際應用中,文件上傳以後,應該往數據庫插入記錄,如 url 相對路徑: uploadFiles/222.png,下面由於只是做爲演示,文件上傳以後,直接返回了瀏覽器訪問的 url 路徑了,並無保存數據。
import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.PostMapping; 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; /** * Created by Administrator on 2019/3/17 0017. */ @Controller public class UploadFileController { @Value("${uploadFile.resourceHandler}") private String resourceHandler;//請求 url 中的資源映射,不推薦寫死在代碼中,最好提供可配置,如 /uploadFiles/** @Value("${uploadFile.location}") private String uploadFileLocation;//上傳文件保存的本地目錄,使用@Value獲取全局配置文件中配置的屬性值,如 E:/wmx/uploadFiles/ /** * 文件上傳,由於只是演示,因此使用 @ResponseBody 將結果直接返回給頁面 * * @param multipartFile * @param request * @return * @throws IOException */ @PostMapping("uploadFile") @ResponseBody public String uploadFile(MultipartFile multipartFile, HttpServletRequest request) throws IOException { if (multipartFile == null || multipartFile.isEmpty()) { return "上傳文件爲空..."; } //basePath拼接完成後,形如:http://192.168.1.20:8080/fileServer String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + request.getContextPath(); String fileName = multipartFile.getOriginalFilename(); String fileServerPath = basePath + resourceHandler.substring(0, resourceHandler.lastIndexOf("/") + 1) + fileName; System.out.println("文件訪問路徑:" + fileServerPath); File saveFile = new File(uploadFileLocation, fileName); multipartFile.transferTo(saveFile);//文件保存 System.out.println("文件保存路徑:" + saveFile.getPath()); return "<a href='" + fileServerPath + "'>" + fileServerPath + "</a>"; } }