Spring Boot 嵌入式 Tomcat 文件上傳、url 映射虛擬路徑


1、Java web 應用開發完成后如果是導入外置的 Tomcat 的 webapps 目錄的話,那么上傳的文件可以直接的放在應用的 web 目錄下去就好了,瀏覽器可以很方便的進行訪問。

2、Spring Boot 默認使用嵌入式 Tomcat ,將來打包成可執行 Jar 文件進行部署,顯然打成 jar 包后,總不可能再將上傳的文件放在 resources 目錄下去了。

3、Spring Boot 於是提供了 url 地址匹配本地虛擬路徑的功能:

1)上傳文件到服務器,服務器將文件保存到了本地,如:E:\wmx\uploadFiles\222.png

2)用戶訪問應該是服務器地址,如:http://localhost:9393/fileServer/uploadFiles/222.png

3)於是通過配置資源映射,使 url 中的 /uploadFiles/ 映射到本地的 E:\wmx\uploadFiles\ 即可,E:\wmx\uploadFiles 則為虛擬路徑。

文件上傳

1、Java JDK 1.8 + Spring Boot 2.1.3 新建 web 項目,spring boot 版本不同,可能略有差異。

2、spring boot 的 web 組件中的 org.springframework:spring-web 已經集成了文件上傳功能,無需再導入以前的 commons-io、以及 commons-fileupload 了,使用方式和之前的 commons-fileupload 完全一樣。

pom.xml 
1、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>

application.yml

1、應用全局配置文件內容如下:

#配置服務器
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 #自定義上傳文件本地保存路徑

2、文件上傳官網介紹: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.

3、上傳文件存放的目錄,不應該寫死在代碼中,所以上面提供了在配置文件中配置 uploadFile.location 屬性,將來類中使用 @Value 取值即可。

UploadFileController 
1、文件上傳后台控制台層代碼如下,后期實現 虛擬路徑映射本地路徑會修改。

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();
    }
}

index.html

1、前端文件上傳 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 映射虛擬路徑
1、使用資源映射虛擬路徑很簡單,使用 WebMvcConfigurer 擴展配置即可,不熟悉的可以參考《Web 項目 tiger 之3 WebMvcConfigurer 實現登錄與攔截、過濾靜態資源》中的“自定義資源映射”部分。

application.yml
1、首先修改一下 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/ #自定義上傳文件本地保存路徑

WebMvcConfigurer

1、再擴展 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 
1、改寫一下控制器。特別提醒一句:實際應用中,文件上傳之后,應該往數據庫插入記錄,如 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>";
    }
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM