SpringBoot檔案上傳+進度條(thymeleaf)
阿新 • • 發佈:2022-05-11
1. 環境搭建
新建springboot專案,新增web 和 thymeleaf 依賴
<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>
2. 介面編寫
package com.xie.controller; 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.RestController; import org.springframework.web.multipart.MultipartFile; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.File; import java.io.IOException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.UUID; /** * @Description * @Date 2022-05-10 9:36 * @Author xie */ @RestController @RequestMapping("/file") public class FileController { private static final String TMP_PATH = "D:/projects/tmp"; @PostMapping("/upload") public String upload(@RequestParam("uploadFile") MultipartFile file, HttpServletRequest request, HttpServletResponse response) { if (file.isEmpty()) { return "檔案為空"; } // 獲取當前時間 String currentDate = new SimpleDateFormat("/yyyy/MM/dd").format(new Date()); // 儲存檔案的目錄 String folderPath = TMP_PATH + currentDate; System.out.println("儲存的路徑地址:" + folderPath); // 判斷是否需要建立目錄 File folderFile = new File(folderPath); if (!folderFile.exists()) { folderFile.mkdirs(); } // 檔名 String fileName = file.getOriginalFilename(); fileName = String.valueOf(UUID.randomUUID()).replace("-", "") + fileName.substring(fileName.lastIndexOf(".")); try { File destFile = new File(folderFile, fileName); System.out.println(destFile.getAbsolutePath()); // 核心 file.transferTo(destFile); String url = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + "/img" + currentDate + fileName; System.out.println(String.format("上傳成功,圖片路徑:%s", url)); return "上傳成功"; } catch (IOException e) { return "上傳失敗"; } } }
3. 前端頁面
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>檔案上傳</title> <style type="text/css"> progress { background-color: #56BE64; } progress::-webkit-progress-bar { background: #ccc; } progress::-webkit-progress-value { background: #56BE64; } percentage { position: fixed; left: 160px; } </style> <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script> </head> <body> <h1>Spring Boot file upload example</h1> <form id="FileuploadForm" method="POST" action="/file/upload" enctype="multipart/form-data"> <input type="file" name="uploadFile" id="uploadFile"/><br/> <br/> <input type="button" id="btnUpload" value="上傳檔案" onclick="upload()"/> <div id="msg"></div> </form> <!--進度條部分(預設隱藏)--> <div style="display: none;" class="progress-body"> <div> <span style="width: 100px; display: inline-block; text-align: right">上傳進度:</span> <progress></progress> <percentage>0%</percentage> </div> <div> <span style="width: 100px; display: inline-block; text-align: right">上傳速度:</span> <span style="width: 300px;" class="progress-speed">0 M/S, 0/0M</span> </div> <div> <span style="width: 100px; display: inline-block; text-align: right">上傳狀態:</span> <span style="width: 300px;" class="progress-info">請選擇檔案並點選上傳檔案按鈕</span> </div> </div> <script> // 上傳檔案 function upload() { $("#msg").text(""); var checkFile = $("#uploadFile").val(); var msgInfo = ""; if (null == checkFile || "" == checkFile) { $("#msg").text("檔案為空,請選擇檔案!"); } else { var formData = new FormData(document.getElementById("FileuploadForm")); $.ajax({ type: "POST", enctype: 'multipart/form-data', url: 'file/upload', data: formData, cache: false, processData: false, contentType: false, error: function (result) { console.log("error"); console.log(result); flag = false; $("#msg").text("訪問伺服器錯誤,請重試!"); }, success: function (result) { console.log("success"); }, xhr: function () { var xhr = $.ajaxSettings.xhr(); if (xhr.upload) { $("#btnUpload").attr("disabled", true); $("#uploadFile").attr("disabled", true); //處理進度條的事件 xhr.upload.addEventListener("progress", progressHandle, false); //載入完成的事件 xhr.addEventListener("load", completeHandle, false); //加載出錯的事件 xhr.addEventListener("error", failedHandle, false); //載入取消的事件 xhr.addEventListener("abort", canceledHandle, false); //開始顯示進度條 showProgress(); return xhr; } } }, 'json'); } } var start = 0; //顯示進度條的函式 function showProgress() { start = new Date().getTime(); $(".progress-body").css("display", "block"); } //隱藏進度條的函式 function hideProgress() { $("#uploadFile").val(''); $('.progress-body .progress-speed').html("0 M/S, 0/0M"); $('.progress-body percentage').html("0%"); $('.progress-body .progress-info').html("請選擇檔案並點選上傳檔案按鈕"); $("#btnUpload").attr("disabled", false); $("#uploadFile").attr("disabled", false); //$(".progress-body").css("display", "none"); } //進度條更新 function progressHandle(e) { $('.progress-body progress').attr({value: e.loaded, max: e.total}); var percent = e.loaded / e.total * 100; var time = ((new Date().getTime() - start) / 1000).toFixed(3); if (time == 0) { time = 1; } $('.progress-body .progress-speed').html(((e.loaded / 1024) / 1024 / time).toFixed(2) + "M/S, " + ((e.loaded / 1024) / 1024).toFixed(2) + "/" + ((e.total / 1024) / 1024).toFixed(2) + " MB. "); $('.progress-body percentage').html(percent.toFixed(2) + "%"); if (percent == 100) { $('.progress-body .progress-info').html("上傳完成,後臺正在處理..."); } else { $('.progress-body .progress-info').html("檔案上傳中..."); } }; //上傳完成處理函式 function completeHandle(e) { $('.progress-body .progress-info').html("上傳檔案完成。"); setTimeout(hideProgress, 2000); }; //上傳出錯處理函式 function failedHandle(e) { $('.progress-body .progress-info').html("上傳檔案出錯, 服務不可用或檔案過大。"); setTimeout(hideProgress, 2000); }; //上傳取消處理函式 function canceledHandle(e) { $('.progress-body .progress-info').html("上傳檔案取消。"); setTimeout(hideProgress, 2000); }; </script> </body> </html>
4. 測試上傳
4.1 SpringBoot 預設配置的 最大檔案上傳大小 和 最大請求大小 都是10MB,為了能夠清楚看到進度條效果配置成500MB。
spring:
http:
multipart:
max-file-size: 500MB # -1 代表不限制
max-request-size: 500MB # -1 代表不限制
thymeleaf:
cache: false
encoding: UTF-8