一篇文章帶你搞定 SpringBoot 上傳文件(單文件/多文件/Ajax上傳)

一、前期配置

在這裏插入圖片描述
同樣不需要額外配置添加一個 web 功能模塊即可

二、單文件上傳

上傳頁面 index.html 位置放在了 static 目錄下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<!--enctype:encodetype編碼類型-->
<form action="/upload" method="post" enctype="multipart/form-data">
    <input type="file" name="file">
    <input type="submit" value="提交">
</form>
</body>
</html>

知識點:enctype="multipart/form-data"

enctype 意思是encodetype就是編碼類型
multipart/form-data是指表單數據有多部分構成,既有文本數據,又有文件等二進制數據的意思。
需要注意的是:默認情況下,enctype的值是application/x-www-form-urlencoded,不能用於文件上傳,只有使用了multipart/form-data,才能完整的傳遞文件數據

FileUploadController:

@RestController
public class FileUploadController {

    private static final Logger log = LoggerFactory.getLogger(FileUploadController.class);
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
	//MultipartFile  這個類一般是用來接受前臺傳過來的文件
    @PostMapping("/upload")
    public Map<String, String> upload(@RequestParam("file") MultipartFile file, HttpServletRequest request) throws IOException {
        //日誌打印文件信息
        log.info("[文件類型] - [{}]", file.getContentType());
        log.info("[文件名稱] - [{}]", file.getOriginalFilename());
        log.info("[文件大小] - [{}]", file.getSize());
        //設置存儲位置
        String format = sdf.format(new Date());
        String path = "D:\\flv\\" + format;
        System.out.println(path);
        File folder = new File(path);
        if (!folder.exists()) {
            folder.mkdirs();
        }
        String oldName = file.getOriginalFilename();
        String newName = UUID.randomUUID().toString() + oldName.substring(oldName.lastIndexOf("."));
        //將文件寫入到指定的目錄中
        file.transferTo(new File(folder, newName));
        System.out.println("getScheme:" + request.getScheme());
        System.out.println("getServerName:" + request.getServerName());
        System.out.println("getServerPort" + request.getServerPort());
        //頁面回顯數據
        Map<String, String> result = new HashMap<>(16);
        result.put("contentType", file.getContentType());
        result.put("fileName", file.getOriginalFilename());
        result.put("fileSize", file.getSize() + "");
        return result;
    }
}

知識點HashMap(int initialCapacity)

hashMap源碼中initialCapacity的初始值爲16,負載因子爲0.75;
所以一個hashMap中默認存儲長度爲16 * 0.75 = 12,也就是如果hashMap.put的鍵值對數量小於12的時候,hashMap位置夠用;但是當添加的鍵值對數超過12後,hashMap需要擴容,一倍,也就是長度從12擴容到24;
例如鍵值對一共13個,這樣剩餘11個位置性能都浪費了,那麼如果已知需要添加的鍵值對數量,就可以通過設置initialMap的值,來避免hashMap擴容,減少性能消耗。
eg:我們需要往hashMap中添加6個鍵值對,6 / 0.75 = 8;那就可以把initialCapacity設置爲9比較合適,節省性能。

在這裏插入圖片描述

三、多文件上傳

index.html

<form action="/uploads" method="post" enctype="multipart/form-data">
    <input type="file" name="files" multiple>
    <input type="submit" value="提交">
</form>

FileUploadController:

 @PostMapping("/uploads")
    public String uploads(@RequestParam("files") MultipartFile[] files, HttpServletRequest request) throws IOException {

        //設置存儲位置
        String format = sdf.format(new Date());
        String path = "D:\\flv\\" + format;
        System.out.println(path);
        File folder = new File(path);
        if (!folder.exists()) {
            folder.mkdirs();
        }
        for (MultipartFile file : files) {
            String oldName = file.getOriginalFilename();
            String newName = UUID.randomUUID().toString() + oldName.substring(oldName.lastIndexOf("."));
            //將文件寫入到指定的目錄中
            file.transferTo(new File(folder, newName));
            String filePath = path + "\\" + newName;
            System.out.println(filePath);
        }
        return "success";
    }

在這裏插入圖片描述

四、Ajax 實現文件上傳

主要是請求你頁面的改變,對於

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="jquery3.3.1.js"></script>
</head>
<body>
<div id="result"></div>
<input type="file" id="file">
<input type="button" value="上傳" onclick="uploadFile()">
<script>
    function uploadFile() {
        var file = $("#file")[0].files[0];
        var formData = new FormData();
        formData.append("file", file);
        $.ajax({
            type:'post',
            url:'/upload',
            processData:false,
            contentType:false,
            data:formData,
            success:function (msg) {
                $("#result").html(msg);
            }
        })
    }
</script>
</body>
</html>

知識點:Ajax 屬性

processData:處理數據
默認情況下,processData 的值是 true,其代表以對象的形式上傳的數據都會被轉換爲字符串的形式上傳。而當上傳文件的時候,則不需要把其轉換爲字符串,因此要改成false
contentType:發送數據的格式
和 contentType 有個類似的屬性是 dataType , 代表的是期望從後端收到的數據的格式,一般會有 json 、text……等而 contentType 則是與 dataType 相對應的,其代表的是前端發送數據的格式,默認值:application/x-www-form-urlencoded,代表的是 ajax 的 data 是以字符串的形式 如 id=2019&password=123456 使用這種傳數據的格式,無法傳輸複雜的數據,比如多維數組、文件等
url:請求路徑
data:請求參數
callback:回調函數
type:響應結果的類型

有時候要注意,自己所傳輸的數據格式和ajax的contentType格式是否一致,如果不一致就要想辦法對數據進行轉換
把contentType 改成 false 就會改掉之前默認的數據格式,在上傳文件時就不會報錯了。

在這裏插入圖片描述

五、屬性配置

默認情況下 Spring Boot 無需做任何配置也能實現文件上傳的功能,但有可能因默認配置不符而導致文件上傳失敗問題,

所以也可以按照對應的情況在 application.properties 中設置對應的屬性;

# 上傳文件的臨時目錄 (一般情況下不用特意修改)
spring.servlet.multipart.location=
# 上傳文件最大爲 1M (默認值 1M 根據自身業務自行控制即可)
spring.servlet.multipart.max-file-size=1048576
# 判斷是否要延遲解析文件(相當於懶加載,一般情況下不用特意修改)
spring.servlet.multipart.resolve-lazily=false
# 禁用 thymeleaf 緩存
spring.thymeleaf.cache=false
# 是否支持批量上傳   (默認值 true)
spring.servlet.multipart.enabled=true
# 上傳請求最大爲 10M(默認值10M 根據自身業務自行控制即可)
spring.servlet.multipart.max-request-size=10485760
# 文件大小閾值,當大於這個閾值時將寫入到磁盤,否則存在內存中,(默認值0 一般情況下不用特意修改)
spring.servlet.multipart.file-size-threshold=0
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章