Spring Boot 處理文件上傳及路徑回顯


實驗介紹

1.1 實驗內容

文件上傳是比較常見和被用戶熟知的功能模塊,常用場景有頭像設置、產品預覽圖、報表文件保存等等,在這些場景中都需要使用到文件上傳功能,本篇文章將會對文件上傳的大致流程及功能設計進行詳細的介紹,並結合實踐案例講解如何使用 Spring Boot 實現文件上傳及相關注意事項,對文件上傳的整個流程進行閉環。

1.2 實驗知識點

  • Spring MVC 文件上傳流程
  • Spring Boot 文件上傳功能實現
  • Spring Boot 文件上傳路徑回顯

1.3 實驗環境

  • JDK 1.8 或者更高版本
  • Spring Boot 2.1.0-RELEASE
  • Maven 3+

1.4 代碼獲取

wget https://labfile.oss.aliyuncs.com/courses/1244/lou-springboot-08.zip
unzip lou-springboot-08.zip
cd lou-springboot

Spring MVC 文件上傳流程

以往在使用 Spring 的 web 項目開發中,我們通常會使用 Spring MVC 框架提供的文件上傳工具類進行文件上傳,也就是 MultipartResolver ,利用 SpringMVC 實現文件上傳功能,離不開對 MultipartResolver 的設置,MultipartResolver 這個類,你可以將其視為 SpringMVC 實現文件上傳功能時的工具類,這個類也只會在文件上傳中發揮作用,在配置了具體實現類之后,SpringMVC 中的 DispatcherServlet 在處理請求時會調用 MultipartResolver 中的方法判斷此請求是不是文件上傳請求,如果是的話 DispatcherServlet 將調用 MultipartResolver 的 resolveMultipart(request) 方法對該請求對象進行裝飾並返回一個新的 MultipartHttpServletRequest 供后繼處理流程使用,注意!此時的請求對象會由 HttpServletRequest 類型轉換成 MultipartHttpServletRequest 類型,這個類中會包含所上傳的文件對象可供后續流程直接使用而無需自行在代碼中實現對文件內容的讀取和對象封裝的邏輯。

在 Spring Boot 中也是通過該工具類進行文件上傳,與普通的 Spring web 項目不同的是,Spring Boot 在自動配置 DispatcherServlet 時也配置好了 MultipartResolver ,而無需再像原來那樣在 springmvc 配置文件中增加文件上傳配置的 bean。

Spring Boot 文件上傳功能實現

這一小節將會通過一個文件上傳案例的實現來講解如何使用 Spring Boot 進行文件上傳功能。

常用配置

由於 Spring Boot 自動配置機制的存在,我們並不需要進行多余的設置,只要已經在 pom 文件中引入了 web starter 模塊即可直接進行文件上傳功能,在前面的實驗中我們已經將 web 模塊整合到項目中,因此無需再進行整合。雖然不用配置也可以使用文件上傳,但是有些開發者可能會在文件上傳時有一些特殊的需求,因此也需要對 Spring Boot 中 MultipartFile 的常用設置進行介紹,配置和默認值如下:

配置含義注釋:

  • spring.servlet.multipart.enabled
    是否支持 multipart 上傳文件,默認支持

  • spring.servlet.multipart.file-size-threshold
    文件大小閾值,當大於這個閾值時將寫入到磁盤,否則存在內存中,(默認值 0 ,一般情況下不用特意修改)

  • spring.servlet.multipart.location
    上傳文件的臨時目錄

  • spring.servlet.multipart.max-file-size
    最大支持文件大小,默認 1 M ,該值可適當的調整

  • spring.servlet.multipart.max-request-size=10Mb
    最大支持請求大小,默認 10 M

  • spring.servlet.multipart.resolve-lazily
    判斷是否要延遲解析文件(相當於懶加載,一般情況下不用特意修改)

上傳功能實現

注意:項目統一創建在/home/project/lou-springboot 目錄下。

創建文件上傳保存目錄

mkdir /home/project/upload

新建文件上傳頁面
在 static 目錄中新建 upload-test.html,上傳頁面代碼如下:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>Spring Boot 文件上傳測試</title>
  </head>
  <body>
    <form action="/upload" method="post" enctype="multipart/form-data">
      <input type="file" name="file" />
      <input type="submit" value="文件上傳" />
    </form>
  </body>
</html>

這應該是大家都很熟悉的一個文件上傳頁面 demo ,文件上傳的請求地址為 /upload,請求方法為 post,需要注意的是在文件上傳時要設置 enctype="multipart/form-data",頁面中包含一個文件選擇框和一個提交框,如下所示:

新建文件上傳處理 Controller
在 com.lou.springboot.controller 包下新建 UploadController,代碼如下:

package com.lou.springboot.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Random;

@Controller
public class UploadController {
    // 文件保存路徑  主要需要自己先建立對應upload文件夾路徑
    private final static String FILE_UPLOAD_PATH = "/home/project/upload/";
    @RequestMapping(value = "/upload", method = RequestMethod.POST)
    @ResponseBody
    public String upload(@RequestParam("file") MultipartFile file) {
        if (file.isEmpty()) {
            return "上傳失敗";
        }
        String fileName = file.getOriginalFilename();
        String suffixName = fileName.substring(fileName.lastIndexOf("."));
        //生成文件名稱通用方法
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd_HHmmss");
        Random r = new Random();
        StringBuilder tempName = new StringBuilder();
        tempName.append(sdf.format(new Date())).append(r.nextInt(100)).append(suffixName);
        String newFileName = tempName.toString();
        try {
            // 保存文件
            byte[] bytes = file.getBytes();
            Path path = Paths.get(FILE_UPLOAD_PATH + newFileName);
            Files.write(path, bytes);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return "上傳成功";
    }
}

由於已經自動配置了 MultipartFile ,因此能夠直接在控制器方法中使用 MultipartFile 讀取文件信息, @RequestParam 中的文件名稱需要與文件上傳前端頁面設置的 name 屬性一致,如果文件為空則返回上傳失敗,如果不為空則生成一個新的文件名,之后讀取文件流並寫入到指定的上傳路徑中,最后返回上傳成功。

文件上傳功能測試

重啟項目,打開瀏覽器並輸入測試頁面地址https://93c7f0974014.simplelab.cn/upload-test.html,之后選擇需要上傳的文件並進行點擊上傳按鈕,之后可以等待后端業務處理了,如果看到上傳成功的提示,並且在 upload 目錄中看到保存的新文件文件則表示功能實現成功,如果文件較大可以適當調整配置項的值。



Spring Boot 文件上傳路徑回顯

網上很多的 Spring Boot 文件上傳教程,通常只講如何實現上傳功能,之后就不再繼續講解了,雖然也給了教程和代碼,但是正常情況下,我們上傳文件是要實際應用到業務中的,比如圖片上傳,上傳后我們需要知道它的路徑,最好能夠在頁面中直接看到它的回顯效果,像前一個步驟中,我們只是成功的完成了文件上傳,但是如何去訪問這個文件還不得而知。Spring Boot 不像普通的 web 項目可以上傳到 webapp 指定目錄中,通常的做法是使用自定義靜態資源映射目錄,以此來實現文件上傳整個流程的閉環,比如前一小節中的實際案例,在文件上傳到 upload 目錄后,增加一個自定義靜態資源映射,使得 upload 下的靜態資源可以通過該映射地址被訪問到,實現方法如下:

package com.lou.springboot.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class SpringBootWebMvcConfigurer implements WebMvcConfigurer {
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
    registry.addResourceHandler("/files/**").addResourceLocations("file:/home/project/upload/");
    }
}

通過該設置,所有以 /files/ 開頭的靜態資源請求都會映射到/home/project/upload/目錄下,

接下來修改UploadController

package com.lou.springboot.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Random;

@Controller
public class UploadController {

    private final static String FILE_UPLOAD_PATH = "/home/project/upload/";

    @RequestMapping(value = "/upload", method = RequestMethod.POST)
    @ResponseBody
    public String upload(@RequestParam("file") MultipartFile file) {
        if (file.isEmpty()) {
            return "上傳失敗";
        }
        String fileName = file.getOriginalFilename();
        String suffixName = fileName.substring(fileName.lastIndexOf("."));
        //生成文件名稱通用方法
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd_HHmmss");
        Random r = new Random();
        StringBuilder tempName = new StringBuilder();
        tempName.append(sdf.format(new Date())).append(r.nextInt(100)).append(suffixName);
        String newFileName = tempName.toString();
        try {
            // 保存文件
            byte[] bytes = file.getBytes();
            Path path = Paths.get(FILE_UPLOAD_PATH + newFileName);
            Files.write(path, bytes);

        } catch (IOException e) {
            e.printStackTrace();
        }
        return "上傳成功,圖片地址為:/files/" + newFileName;
    }
}

測試

接下來我們來測試一下上傳的文件能否被訪問到,重啟項目並,在項目啟動成功后,可以點擊頁面上方的 Web 服務直接在顯示查看網站效果。

之后會在瀏覽器中彈出https://********.simplelab.cn 頁面,我們可以在瀏覽器中輸入如下地址打開文件上傳測試頁面:https://160d612088bc.simplelab.cn/upload-test.html,之后進行文件上傳測試和路徑回顯測試,過程如下所示:

最后,需要確認一下 upload 目錄下是否存在該文件,如下圖所示:

實驗總結

本篇文章首先對文件上傳的流程及功能設計進行了介紹,之后結合實踐案例講解如何使用 Spring Boot 實現文件上傳以及如何對已上傳的文件進行路徑回顯,希望通過本實驗的講解,大家都能夠掌握如何使用 Spring Boot 進行文件上傳,本文演示時都是使用的圖片文件,同學們在練習時也可以使用其他格式的文件進行測試,希望大家多多動手練習,以更快的掌握該知識點,后續在圖片管理模塊實踐中我們會繼續對該功能進行拓展講解


免責聲明!

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



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