springboot 文件上傳示例(webuploader插件)


1.情景展示

文件上傳,在開發過程中,經常會用到,springboot如何接收上傳文件?

本文將以springboot為例,如何接收前端的文件請求;

上傳文件使用插件更方便,這里我使用webuploader。

2.前端代碼

第一步:准備webuploader插件放到項目當中;

由於,springboot在項目啟動的時候,會自動將static目錄下的靜態資源(前端代碼)加載到項目當中;

所以,我這里為了省事兒,就不創建web目錄了;

而且springboot還會自動將resources/static目錄下的index.html當做項目的歡迎頁(我這里為了省事,就沒有配置請求與頁面想對照的映射關系)。

現在,我們來對前端代碼進行整體認知;

一個要存放插件的位置:webuploader;

一個要展示插件的頁面:index.html;

一個要處理文件上傳的js:upload.js;

index.html需要引入:

webuploader.css和webuploader.js;

必須在webuploader.js引入之前引入jQuery.js(因為它依賴jQuery);

include.js包含的內容如下:

// 獲取請求路徑
var pathName = window.document.location.pathname;
// 通過截取得到項目名稱
var baseUrl = pathName.substring(0, pathName.substr(1).indexOf('/') + 1);

用途:獲取該項目的名稱。

html的核心代碼為:

<div id="filePicker" style="line-height:15px;" class="webuploader-container">
    <div class="webuploader-pick">選擇文件</div>
</div>

webuploader插件會通過init()方法,對filePicker這個div里面追加內容,例如:

js核心代碼:

查看代碼
/**
 * 該插件批量上傳的本質:
 * 每個文件單獨發送一個上傳請求,所以,其本質還是單文件上傳,而不是真正含義上的:一次請求包含多個文件。
 */
this.init = function () {
    var  state = 'pending';
    var upUrl = baseUrl + '/file/upload.do';
    var uploader = WebUploader.create({
        auto: true, // 選擇文件后自動上傳,默認不自動上傳需要觸發
        swf: baseUrl + '/webuploader/Uploader.swf', // swf文件路徑
        server: upUrl, // 上傳文件的接口(替換成你們后端給的接口路徑) 
        // 選擇文件的按鈕。可選。
        // 內部根據當前運行是創建,可能是input元素,也可能是flash.
        pick: '#filePicker',
        accept: {
	            //extensions: 'xls,xlsx', // 允許的文件后綴,不帶點,多個用逗號分割,這里支持老版的Excel和新版的
	            mimeTypes: 'application/vnd.ms-excel,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
                // 說明:extensions沒用,不生效
                // 只有mimeTypes的值對應文件域的accept屬性,僅能通過它來控制上傳文件的類型
                // 文件類型,也可以通過&ldquo;.后綴名&rdquo;的方式來實現,如:.xls,.xlsx
	    },
        resize: false, // 不壓縮image, 默認如果是jpeg,文件上傳前會壓縮一把再上傳!
       /*  duplicate :true */ //可重復上傳
    });

    /**
     * 文件被加入隊列之前觸發
     * @explain 主要用來傳其它參數
     */
    uploader.on('beforeFileQueued', function (file) {
        var obj = new Object();
        obj.THEMEID = $('#THEMEID').val();
        uploader.options.formData = obj;
    });

    /**
     * 上傳成功
     */
    uploader.on('uploadSuccess', function( file, result) {
        alert(JSON.stringify(result));
    });

    /**
     * 上傳失敗
     */
    uploader.on('uploadError', function( file, result) {
        // alert('文件上傳失敗!');
        alert(JSON.stringify(result));
    });

    /**
     * 上傳完成
     */
    uploader.on( 'uploadComplete', function( file ) {
        
    });

    uploader.on( 'all', function( type ) {
        if ( type === 'startUpload' ) {
            state = 'uploading';
        } else if ( type === 'stopUpload' ) {
            state = 'paused';
        } else if ( type === 'uploadFinished' ) {
            state = 'done';
        }
    });
}

HTML完整代碼:

查看代碼
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>文件上傳</title>
    <link rel="stylesheet" type="text/css" href="webuploader/webuploader.css">
    <script type="text/javascript" src="common/js/jquery-3.6.0.min.js"></script>
    <script type="text/javascript" src="webuploader/webuploader.js"></script>
    <script type="text/javascript" src="common/js/include.js"></script>
    <script type="text/javascript" src="upload.js"></script>
</head>
<body>
    <h1>歡迎來到Marydon的博客園</h1>
    <table border="0" cellpadding="0" cellspacing="0" style="width: 100%; height: 90%">
        <tr>
            <td style="text-align: center">
                <div id="filePicker" style="line-height:15px;" class="webuploader-container">
                    <div class="webuploader-pick">選擇文件</div>
                </div>
            </td>
            <td>
                <span style="color: #898989">備注:掃描文件格式為xls</span>
            </td>
        </tr>
    </table>
</body>
</html>

注意:關鍵點在於,引入文件的路徑問題,不要搞錯了。 

JAVASCRIPT完整代碼:

查看代碼
var upload = new Upload();
window.onload = function(){
	// 不要忘了調用WebUploader的初始化函數
	upload.init();
}

function Upload() {
    var object = this;

	/**
	 * 該插件批量上傳的本質:
	 * 每個文件單獨發送一個上傳請求,所以,其本質還是單文件上傳,而不是真正含義上的:一次請求包含多個文件。
	 */
	this.init = function () {
    	var uploadUrl = baseUrl + '/file/upload.do';
	    var uploader = WebUploader.create({
	        auto: true, // 選擇文件后自動上傳,默認不自動上傳需要觸發
	        swf: baseUrl + '/webuploader/Uploader.swf', // swf文件路徑
	        server: uploadUrl, // 上傳文件的接口(替換成你們后端給的接口路徑) 
	        // 選擇文件的按鈕。可選。
	        // 內部根據當前運行是創建,可能是input元素,也可能是flash.
	        pick: '#filePicker',
	        accept: {
	            //extensions: 'xls,xlsx', // 允許的文件后綴,不帶點,多個用逗號分割,這里支持老版的Excel和新版的
	            mimeTypes: 'application/vnd.ms-excel,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
                // 說明:extensions沒用,不生效
                // 只有mimeTypes的值對應文件域的accept屬性,僅能通過它來控制上傳文件的類型
                // 文件類型,也可以通過“.后綴名”的方式來實現,如:.xls,.xlsx
	        },
	        resize: false, // 不壓縮image, 默認如果是jpeg,文件上傳前會壓縮一把再上傳!
	       /*  duplicate :true */ //可重復上傳
	    });

		/**
		 * 文件被加入隊列之前觸發
		 * @description 主要用來傳其它參數
		 * @explain 我沒有在這里演示,沒有傳其它參數
		 */
		uploader.on('beforeFileQueued', function (file) {
	        var obj = new Object();
	        obj.THEMEID = $('#THEMEID').val();
			uploader.options.formData = obj;
		});

		/**
		 * 上傳成功
		 */
		uploader.on('uploadSuccess', function( file, result) {
			alert(JSON.stringify(result));
		});

		/**
		 * 上傳失敗
		 */
		uploader.on('uploadError', function( file, result) {
			// alert('文件上傳失敗!');
			alert(JSON.stringify(result));
		});

	};
}

注意:關鍵點在於,需要對插件WebUploader進行初始化。

3.后端代碼

難點在於:如何接收前端發過來的請求?

其實,很簡單:參數file的值就是MultipartFile類型的文件。

文件上傳,上傳的參數至少會有以下6個參數:

為了方便對於參數的使用,我用實體類來接收這些參數,這樣,在后續用到的時候就會很方便。

查看代碼
import lombok.Getter;
import lombok.Setter;
import org.springframework.web.multipart.MultipartFile;

import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;

/**
 * 文件上傳請求參數
 * @description:
 * @author: Marydon
 * @date: 2022-01-10 15:38
 * @version: 1.0
 * @email: marydon20170307@163.com
 */
@Getter
@Setter
public class UploadParamsDto {
    @NotBlank(message = "id:不能為空")
    private String id;
    @NotBlank(message = "name:不能為空")
    private String name;
    @NotBlank(message = "type:不能為空")
    private String type;
    @NotBlank(message = "lastModifiedDate:不能為空")
    private String lastModifiedDate;
    @NotBlank(message = "size:不能為空")
    private String size;
    @NotNull(message = "file:不能為空")
    private MultipartFile file;
}

如果不需要對參數進行非空校驗,刪掉這些屬性對應的注解即可。

JAVA控制層完成代碼:

查看代碼
import com.example.upload.web.dto.UploadParamsDto;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

/**
 * 文件上傳控制層
 * @description:
 * @author: Marydon
 * @date: 2022-01-10 10:16
 * @version: 1.0
 * @email: marydon20170307@163.com
 */
@Slf4j
@RestController
@RequestMapping("/file")
public class UploadController {
    // 文件存放路徑:項目路徑/files
    private static final String UPLOADED_FOLDER = System.getProperty("user.dir") + File.separator + "files";

    /*
     * 文件上傳
     * @attention: 不支持批量上傳
     * @description: 請求類型-multipart/form-data
     * @date: 2022/1/11 10:23
     * @param: paramsDto
     * @return: java.util.Map
     */
    @PostMapping("/upload.do")
    public Map<String, Object> upload(@Validated UploadParamsDto paramsDto) {
        // 即將返回的數據
        Map<String, Object> resultMap = new HashMap<>(2);
        resultMap.put("isSuccess", true);
        resultMap.put("error", "");

        Map<String, String> errorMap = new HashMap<>();
        // 獲取上傳的文件
        MultipartFile file = paramsDto.getFile();
        // 新文件的文件名
        String fileName = System.currentTimeMillis() + "_" + paramsDto.getName();
        // 新文件的生成
        File copyFile = new File(UPLOADED_FOLDER + File.separator + fileName);
        // 目錄不存在就自動創建
        copyFile.mkdirs();
        try {
            // 將multipartfile文件轉移到file對象所代表的文件中
            // 該方法可以將文件夾直接變為文件
            // 當copyFile代表的是一個目錄時,正常情況文件是無法輸入的,而transferTo()方法會將該目錄直接變為文件並輸入數據
            file.transferTo(copyFile);
        } catch (IOException e) {
            e.printStackTrace();
            log.error(e.getMessage());
            // 如果報錯,意味着該文件上傳失敗,將原文件名和報錯信息返回
            errorMap.put(paramsDto.getName(), e.getMessage());
        }

        if (!errorMap.isEmpty()) {
            resultMap.put("error", errorMap);
        }

        return resultMap;
    }
}

難點還有:如何獲取保存文件的目錄;

新文件名的命名規則;

文件的快速復制。

當然,如果只是根據上傳的文件進行解析處理,而不保存的話,不會遇到以上3個問題。

說明:

請求格式:multipart/form-data;

返回格式:application/json。

另外,如果,需要對實體類UploadParamsDto進行參數校驗,除了需要在它前面加注解@Validated外,還要引入對應的注解jar依賴。

<!--spring對參數進行校驗:hibernate validator-->
<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-validator</artifactId>
    <version>6.0.18.Final</version>
</dependency>

更多細節,我在之前的文章講過。 

4.效果展示

直接來到歡迎頁

點擊“選擇文件”,選擇要上傳的文件,支持多選。

最終上傳的文件存放位置

5.擴展

通過配置文件限制上傳文件大小

如果,對上傳文件的大小有限制的話,可以通過配置來實現。

查看代碼

####spring配置####
####開發環境數據源配置
spring:
  ###文件上傳大小限制
  servlet:
    multipart:
      #是否支持批量上傳(默認值 true)
      enabled: true
      #上傳文件最大為 1M(默認值 1M)
      max-file-size: 10MB
      #上傳請求最大為 10M(默認值 10M)
      max-request-size: 10MB
      #文件大小閾值,當大於這個閾值時將寫入到磁盤,否則存在內存中(默認值0,即:直接將文件寫入磁盤)
      file-size-threshold: 0
      #判斷是否要延遲解析文件(默認值false)
      resolve-lazily: false
      #存放上傳文件的臨時目錄
      location:

禁止多選

WebUploader插件,默認支持多文件上傳;

如果我們需要限制每次只允許上傳一個文件的話,可以通過如下配置進行禁止。

pick對象里面聲明multiple屬性,並將值設為false。

pick: {
	'id': '#filePicker',//文件上傳按鈕所在位置(通過ID來指定)
	'multiple': false //禁止多選
},

頁面初始化后,文本域沒有multiple屬性。

 

下面這種方式,會默認允許多選。

 

說明:

文件域的multiple屬性,可以控制文件的單選和多選;

支持多選:聲明multiple屬性;

禁止多選:不聲明multiple屬性。

<input type="file" multiple="multiple">

文件域的accept屬性,可以控制上傳文件的文件類型。

方式一:

<input type="file" accept="文件對應的文件類型(mimetype),如:application/pdf">

方式二:推薦使用

<input type="file" accept="文件對應的文件后綴名(.文件名),如:.sql">

2023年3月27日15:31:48

上傳jpg文件

當使用該插件上傳jpg格式圖片時,可能會上傳失敗,報錯信息如下:

需要聲明compress屬性,如果不需要壓縮的話,將值設為false即可。

var uploader = WebUploader.create({
    auto: true,
    swf: baseUrl + '/commons/js/ueditor/third-party/webuploader/Uploader.swf',
    server: upUrl,
    pick: '#filePicker',
    method: 'POST',
    resize: false,
    compress: false,// 不聲明將導致部分jpg文件無法上傳
    accept: {
        title: 'Images',
        extensions: 'gif,jpg,jpeg,bmp,png,pdf',
        mimeTypes: 'image/*,application/pdf'
    }
});

 

寫在最后

  哪位大佬如若發現文章存在紕漏之處或需要補充更多內容,歡迎留言!!!

 相關推薦:


免責聲明!

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



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