• SpringBoot文件上传


    SpringBoot文件上传

    文件上传的本质

    文件上传的流程,相当于是复制,是读取了要上传文件的二进制流,并把这个二进制流的信息复制给服务器指定路径的另一个文件

    文件上传的细节点

    • 在服务器中需要有专门的目录来存放上传路径 ,在新的上传请求传来时,必应判断该上传路径是否存在,若不存在 ,则需要先创建该上传目录。

    • 在服务器中的文件,为了防止上传文件的名称重复(防止重复提交同一文件),从而产生冲突等问题,应用 UUID 来生成随机 ID 为新文件命名

    • 文件上传应当将上传至服务器的url地址保存在数据库中

    获取原文件名称

    在前端向后端发起上传请求时,传参中必然带有文件信息,此时在 Controller 层对应的接口中会接收到 MultipartFile 类型的 file

    通过以下代码可获取原文件的信息:

    //原文件名称
    String OriginFileName = file.getOriginalFilename();
    //原文件文件名最大长度
    int fileNamelength = file.getOriginalFilename().length()
    
    • 1
    • 2
    • 3
    • 4

    获取新文件路径(名称)

    /**
         * 编码文件名
         */
        public static final String extractFilename(MultipartFile file)
        {
            String fileName = file.getOriginalFilename();
            //获得文件名后缀
            String extension = getExtension(file);
            //拼接上时间
            fileName = DateUtils.datePath() + "/" + IdUtils.fastUUID() + "." + extension;
            return fileName;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    为什么要拼接上时间,是因为window类似mysql也有自己的索引规则,通过时间来查找,能减轻搜索压力

    将远程文件存入本地

    假设,存放新文件的变量名称为 newFile ,远程文件变量名称为 oldFile

    则可通过以下代码将远程文件保存至本地文件中:

    oldFile.transferTo(newFile);
    
    • 1

    修改上传文件类型

    upload(baseDir, file, MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION);
    
    • 1

    其中DEFAULT_ALLOWED_EXTENSION是上传时候默认携带的一个参数,存储了一个集合(文件类型)
    在这里插入图片描述
    可以发现这里面没有视频的类型,要想该上传可以通过视频类型的文件,可以在这个集合上加上视频对应的类型
    在这里插入图片描述

    案例

    前端采取ElementUI上传的组件

    这个项目上传是需要验证权限的,所以请求时候在请求头携带了一个认证的参数

    
    
    
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80

    后端

    CommonController

    这里处理上传后的文件名称和请求路径进行一个拼接

    public class CommonController {
        @Autowired
        private ServerConfig serverConfig;
        /**
         * 通用上传请求
         */
        @PostMapping("/upload")
        public ResultJson uploadFile(MultipartFile file) throws Exception {
            try {
                // 上传文件路径(配置文件中的)
                String filePath = NiuaConfig.getUploadPath();
                // 上传并返回新文件名称
                String fileName = FileUploadUtils.upload(filePath, file);
                //获取请求路径
                String url = serverConfig.getUrl() + fileName;//http://127.0.0.1:9527
                Map<String, String> prams = new HashMap<String, String>();
                prams.put("fileName", fileName);
                //profile/upload/2022/07/28/94ac7ece-3371-40fb-80d0-8f42231df2f7.jpg
                prams.put("url", url);
                //http://127.0.0.1:9527/profile/upload/2022/07/28/94ac7ece-3371-40fb-80d0-8f42231df2f7.jpg
                return ResultJson.ok(prams);
            } catch (Exception e) {
                return ResultJson.failure(ResultCode.BAD_REQUEST, e.getMessage());
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    获取新文件名称

    String fileName = FileUploadUtils.upload(filePath, file);
    
    • 1

    根据文件路径上传,这里携带了DEFAULT_ALLOWED_EXTENSION参数,表示默认文件上传的类型

     /**
         * 根据文件路径上传
         *
         * @param baseDir 相对应用的基目录
         * @param file 上传的文件
         * @return 文件名称
         * @throws IOException
         */
        public static final String upload(String baseDir, MultipartFile file) throws IOException
        {
            try
            {
                return upload(baseDir, file, MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION);
            }
            catch (Exception e)
            {
                throw new IOException(e.getMessage(), e);
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    文件上传

    /**
         * 文件上传
         *
         * @param baseDir 相对应用的基目录
         * @param file 上传的文件
         * @param allowedExtension 上传文件类型
         * @return 返回上传成功的文件名
         * @throws FileSizeLimitExceededException 如果超出最大大小
         * @throws FileNameLengthLimitExceededException 文件名太长
         * @throws IOException 比如读写文件出错时
         * @throws InvalidExtensionException 文件校验异常
         */
        public static final String upload(String baseDir, MultipartFile file, String[] allowedExtension)
                throws FileSizeLimitExceededException, IOException, FileNameLengthLimitExceededException,
                InvalidExtensionException
        {
            //文件大小检验
            int fileNamelength = file.getOriginalFilename().length();
            if (fileNamelength > FileUploadUtils.DEFAULT_FILE_NAME_LENGTH)
            {
                throw new FileNameLengthLimitExceededException(FileUploadUtils.DEFAULT_FILE_NAME_LENGTH);
            }
            //文件类型检验
            assertAllowed(file, allowedExtension);
            //获取拼接说时间的文件名称(编码新文件名)
            String fileName = extractFilename(file);
    		//返回一个文件的绝对路径
            File desc = getAbsoluteFile(baseDir, fileName);
            //把远程文件存入本地
            file.transferTo(desc);
            String pathFileName = getPathFileName(baseDir, fileName);
            return pathFileName;//profile/upload/2022/07/28/94ac7ece-3371-40fb-80d0-8f42231df2f7.jpg
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    返回的数据格式ResultJson.java

    package tech.niua.common.model;
    
    import lombok.Data;
    
    import java.io.Serializable;
    
    /**
     * @author Wangzhen
     * RESTful API 返回类型
     * createAt: 2020/5/29
     */
    @Data
    public class ResultJson<T> implements Serializable{
    
        private static final long serialVersionUID = 783015033603078674L;
        private int code;
        private String msg;
        private T data;
    
        public static ResultJson ok() {
            return ok("");
        }
    
        public static ResultJson ok(Object o) {
            return new ResultJson(ResultCode.SUCCESS, o);
        }
    
        public static ResultJson failure(ResultCode code) {
            return failure(code, "");
        }
    
        public static ResultJson failure(ResultCode code, Object o) {
            return new ResultJson(code, o);
        }
    
        public ResultJson(ResultCode resultCode) {
            setResultCode(resultCode);
        }
    
        public ResultJson(ResultCode resultCode, T data) {
            setResultCode(resultCode);
            this.data = data;
        }
    
        public void setResultCode(ResultCode resultCode) {
            this.code = resultCode.getCode();
            this.msg = resultCode.getMsg();
        }
    
        @Override
        public String toString() {
            return "{" +
                    "\"code\":" + code +
                    ", \"msg\":\"" + msg + '\"' +
                    ", \"data\":\"" + data + '\"'+
                    '}';
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58

    返回的数据格式ResultJson.java

    package tech.niua.common.model;
    
    import lombok.Data;
    
    import java.io.Serializable;
    
    /**
     * @author Wangzhen
     * RESTful API 返回类型
     * createAt: 2020/5/29
     */
    @Data
    public class ResultJson<T> implements Serializable{
    
        private static final long serialVersionUID = 783015033603078674L;
        private int code;
        private String msg;
        private T data;
    
        public static ResultJson ok() {
            return ok("");
        }
    
        public static ResultJson ok(Object o) {
            return new ResultJson(ResultCode.SUCCESS, o);
        }
    
        public static ResultJson failure(ResultCode code) {
            return failure(code, "");
        }
    
        public static ResultJson failure(ResultCode code, Object o) {
            return new ResultJson(code, o);
        }
    
        public ResultJson(ResultCode resultCode) {
            setResultCode(resultCode);
        }
    
        public ResultJson(ResultCode resultCode, T data) {
            setResultCode(resultCode);
            this.data = data;
        }
    
        public void setResultCode(ResultCode resultCode) {
            this.code = resultCode.getCode();
            this.msg = resultCode.getMsg();
        }
    
        @Override
        public String toString() {
            return "{" +
                    "\"code\":" + code +
                    ", \"msg\":\"" + msg + '\"' +
                    ", \"data\":\"" + data + '\"'+
                    '}';
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58

    返回的数据格式ResultJson.java

    package tech.niua.common.model;
    
    import lombok.Data;
    
    import java.io.Serializable;
    
    /**
     * @author Wangzhen
     * RESTful API 返回类型
     * createAt: 2020/5/29
     */
    @Data
    public class ResultJson<T> implements Serializable{
    
        private static final long serialVersionUID = 783015033603078674L;
        private int code;
        private String msg;
        private T data;
    
        public static ResultJson ok() {
            return ok("");
        }
    
        public static ResultJson ok(Object o) {
            return new ResultJson(ResultCode.SUCCESS, o);
        }
    
        public static ResultJson failure(ResultCode code) {
            return failure(code, "");
        }
    
        public static ResultJson failure(ResultCode code, Object o) {
            return new ResultJson(code, o);
        }
    
        public ResultJson(ResultCode resultCode) {
            setResultCode(resultCode);
        }
    
        public ResultJson(ResultCode resultCode, T data) {
            setResultCode(resultCode);
            this.data = data;
        }
    
        public void setResultCode(ResultCode resultCode) {
            this.code = resultCode.getCode();
            this.msg = resultCode.getMsg();
        }
    
        @Override
        public String toString() {
            return "{" +
                    "\"code\":" + code +
                    ", \"msg\":\"" + msg + '\"' +
                    ", \"data\":\"" + data + '\"'+
                    '}';
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58

    编码新文件名

    通过UUID(避免重复)给文件编码新的文件名,并且按照指定的样式返回

    /**
         * 编码文件名
         */
        public static final String extractFilename(MultipartFile file)
        {
            String fileName = file.getOriginalFilename();
            //获得文件名后缀
            String extension = getExtension(file);
            //拼接上时间
            fileName = DateUtils.datePath() + "/" + IdUtils.fastUUID() + "." + extension;
            return fileName;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    上传成功效果图
    在这里插入图片描述

  • 相关阅读:
    【kafka】-分区-消费端负载均衡
    数字孪生产业园开发公司,VR钢铁效果怎么样?强荐广州华锐互动
    打开Outlook报错修复
    软件工程与计算(十八)代码设计
    PLC中ST编程的定时器
    HttpClient工具类
    18.Redis系列之AOF方式持久化
    安装多个MySQL版本时如何连接到不同的数据库
    ReentrantLock锁与AQS的联系
    一文读懂RPA是什么?互联网运营如何学习RPA
  • 原文地址:https://blog.csdn.net/m0_61820867/article/details/126031100