补:Spring Boot 当中实现文件上传功能(附+源代码)

1. 补:Spring Boot 当中实现文件上传功能(附+源代码)

文章目录

  • [1. 补:Spring Boot 当中实现文件上传功能(附+源代码)](#1. 补:Spring Boot 当中实现文件上传功能(附+源代码))
  • [2. 准备工作](#2. 准备工作)
  • [3. 开始演示:实现文件上传功能(附+源码)](#3. 开始演示:实现文件上传功能(附+源码))
    • [3.1 第一种方式:静态创建方式](#3.1 第一种方式:静态创建方式)
    • [3.2 第二种方式:动态创建方式](#3.2 第二种方式:动态创建方式)
  • [4. 上传文件的注意事项](#4. 上传文件的注意事项)
  • [5. 最后:](#5. 最后:)

2. 准备工作

我们在 pom.xml 文件当中导入相关的 jar 依赖。如下:

xml 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.rainbowsea</groupId>
    <artifactId>springboot-fileUpload</artifactId>
    <version>1.0-SNAPSHOT</version>



    <!--    导入SpringBoot 父工程-规定写法-->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.5.3</version>
    </parent>

    <!--    导入web项目场景启动器:会自动导入和web开发相关的jar包所有依赖【库/jar】-->
    <!--    后面还会在说明spring-boot-starter-web 到底引入哪些相关依赖-->
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--引入lombok-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <!--        引入 thymeleaf-start ,项目会自动完成配置,-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>

        <!--  引入 lombok 插件      -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
    </dependencies>
</project>

编写项目的场景启动器:

java 复制代码
package com.rainbowsea.springboot;


import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication // 项目启动场景
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class,args);
    }
}

编写相关前端 HTML页面,上传文件的页面。

注意:这里我们是前端使用的是 thymeleaf 视图解析器。所以关于前端映射文件的存放位置,不可以随便放。

html 复制代码
enctype="multipart/form-data" 文件提交
multiple 属性可以选中多个文件信息上传
<input type="reset" value="重新填写"><br> ; type="reset" 清空表单,重新填写表单

前端页面显示效果:


3. 开始演示:实现文件上传功能(附+源码)

3.1 第一种方式:静态创建方式

静态创建方式: 静态方式,先手动在指定的 windows 当中创建好目录,再放入上传的文件。到其目录当中。

java 复制代码
package com.rainbowsea.springboot.controller;


import com.rainbowsea.springboot.utils.WebUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Controller;
import org.springframework.util.ResourceUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.util.UUID;

@Slf4j
@Controller  // 控制器
public class UploadController {

    // 处理转发到用户注册~可以完成文件上传页面
    @GetMapping("/upload.html")
    public String uploadPage() {

        return "upload";  // 视图解析,pom_>jar,转发到templates/upload.html
        // 注意如果配置了拦截器,资源的上传 upload.html页面也是要放行的
    }


    // 处理用户的注册请求-包括处理文件上传

    // 静态方式,先手动在指定的windows当中创建目录,在放入文件
    @PostMapping("/upload")
    @ResponseBody
    public String upload(
            // 自动封装
            String name,
            String email,
            Integer age,
            String job,
            @RequestParam("header") MultipartFile header,
            @RequestParam("photos") MultipartFile[] photos
    ) throws IOException {
        log.info("上传的信息 name={},email={} age = {} job={} ",name,email,age,job);
        log.info("header={}",header);
        log.info("photos={}",photos);


        // 如果信息都成功得到,我们就将文件保存到指定的目录比如:E:\temp_upload
        // 1. 我们需要先将文件保存到指定的目录,比如:E:\temp_upload
        // 2. 后面我们在演示把文件保存到动态创建的目录当中
        // 首先处理头像的文件,因为只有一张图片
        if(!header.isEmpty()) {  // 处理头像
            String originalFilename = header.getOriginalFilename();
            System.out.println(originalFilename);
            header.transferTo(new File("E:\\temp_upload\\" +originalFilename) );
        }

        // 处理宠物的图片
        if(photos.length > 0) {
            for (MultipartFile photo :photos) {
                String originalFilename = photo.getOriginalFilename();
                System.out.println(originalFilename);
                photo.transferTo(new File("E:\\temp_upload\\" + originalFilename));
            }
        }



        return "注册用户成功/文件上传成功";
    }
}

运行测试:http://localhost:8080/upload.html


3.2 第二种方式:动态创建方式

动态创建方式: 以项目作为根路径创建目录,存放文件。这种方式兼容性更好,没有盘符之说。可移植性更好。

动态创建的核心,就是获取到项目的根路径,从而以项目的根路径,作为参照/相对路径,从而创建存放上传文件的目录。

java 复制代码
package com.rainbowsea.springboot.controller;


import com.rainbowsea.springboot.utils.WebUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Controller;
import org.springframework.util.ResourceUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.util.UUID;

@Slf4j
@Controller  // 控制器
public class UploadController {

    // 处理转发到用户注册~可以完成文件上传页面
    @GetMapping("/upload.html")
    public String uploadPage() {

        return "upload";  // 视图解析,pom_>jar,转发到templates/upload.html
        // 注意如果配置了拦截器,资源的上传 upload.html页面也是要放行的
    }


    // 处理用户的注册请求-包括处理文件上传
    // 动态创建方式:以项目作为根路径创建目录,存放文件
    // springboot-fileUpload/src/main/resources/static/images
    @PostMapping("/upload")
    @ResponseBody
    public String upload(
            // 自动封装
            String name,
            String email,
            Integer age,
            String job,
            @RequestParam("header") MultipartFile header,
            @RequestParam("photos") MultipartFile[] photos
    ) throws IOException {
        log.info("上传的信息 name={},email={} age = {} job={} ", name, email, age, job);
        log.info("header={}", header);
        log.info("photos={}", photos);


        String path = ResourceUtils.getURL("classpath:").getPath();
        System.out.println("path:" + path);  // 获取到的是这个项目的根路径(类路径)全的。

        // 定义好,我们要在项目中的什么位置存放传过来的文件
        //File file = new File(path + "static/images");

        File file = new File(WebUtils.getUploadFileDirectory());
        // 动态创建指定目录
        if (!file.exists()) { // 如果目录不存在,我们就创建
            file.mkdirs();
        }

        // 首先处理头像的文件,因为只有一张图片
        if (!header.isEmpty()) {  // 处理头像
            String originalFilename = header.getOriginalFilename();  // 获取的文件的名字
            System.out.println(file.getAbsolutePath());  // 获取到文件的绝对路径
            String fileName = UUID.randomUUID().toString() + "_"+ System.currentTimeMillis()+"_"+originalFilename;
            System.out.println(fileName);
            header.transferTo(new File(file.getAbsolutePath() + "/" + fileName));
        }

        // 处理宠物的图片
        if (photos.length > 0) {
            for (MultipartFile photo : photos) {
                String originalFilename = photo.getOriginalFilename();
                System.out.println(file.getAbsolutePath());  // 获取到文件的绝对路径
                String fileName = UUID.randomUUID().toString() + "_"+ System.currentTimeMillis()+"_"+originalFilename;
                // 保存到动态创建的目录
                photo.transferTo(new File(file.getAbsolutePath() + "/" + fileName ));
            }
        }


        return "注册用户成功/文件上传成功";
    }
}

4. 上传文件的注意事项

  1. Spring Boot 的文件上传: 注意如果配置了拦截器,资源的上传 upload.html页面也是要放行的,不然会上传失败。
  2. 注意:在Spring Boot 当中:默认单个文件最大1MB,一次上传多个文件最大10MB,我们可以修改
    MultipartProperties类当中的属性,我们可以通过在 resources类路径下,application.yaml 进行修改
yaml 复制代码
spring:
  servlet:
    multipart:
      max-file-size: 10MB
      max-request-size: 50MB
  1. 解决文件覆盖问题,如果文件名相同,会出现覆盖问题,如何解决。------> 在原本上传的文件的文件名后面+加上+时间戳+哈希值,就避免了文件名的重复了,每个文件都是唯一的了。同时使用 "_" 分割,用于后续,想要获取到真正的文件名,作准备
  1. 解决文件分目录存放问题,如果将文件都上传到一个目录下,当上传文件很多时,会造成文件速度变慢,因此,可以将文件上传到不同目录,比如一天上传的文件,统一放到一个文件夹 年/月/日,比如 2022/11/11目录.

这里我们创建一个工具类,来解决,返回一个以系统的年月日作为目录的字符串。

java 复制代码
package com.rainbowsea.springboot.utils;

import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.SimpleTimeZone;

public class WebUtils {
    private WebUtils() {
    }

    public static String getYearMonthDay() {
        // 如何得到当前的日期-》Java基础 日期,三代类
        LocalDateTime localDateTime = LocalDateTime.now();
        int year = localDateTime.getYear();
        int monthValue = localDateTime.getMonthValue();
        int dayOfMonth = localDateTime.getDayOfMonth();
        String yearMonthDay = year + "-" + monthValue + "-" + dayOfMonth;

        return yearMonthDay;
    }


    /**
     * 以年月日创建目录
     * 返回一个年月日为格式的目录的字符串
     * @return 返回一个年月日为格式的目录的字符串
     */
    public static String getUploadFileDirectory() {
        // 返回一个年月日为格式的目录的字符串
        return "static/images/" + new SimpleDateFormat("yyyy/MM/dd").format(new Date());
    }

    // 测试一下
    public static void main(String[] args) {
        System.out.println(WebUtils.getYearMonthDay());
        System.out.println(getUploadFileDirectory());
    }
}

运行测试:

5. 最后:

"在这个最后的篇章中,我要表达我对每一位读者的感激之情。你们的关注和回复是我创作的动力源泉,我从你们身上吸取了无尽的灵感与勇气。我会将你们的鼓励留在心底,继续在其他的领域奋斗。感谢你们,我们总会在某个时刻再次相遇。"

相关推荐
陈平安Java and C32 分钟前
MyBatisPlus
java
秋野酱1 小时前
如何在 Spring Boot 中实现自定义属性
java·数据库·spring boot
安的列斯凯奇1 小时前
SpringBoot篇 单元测试 理论篇
spring boot·后端·单元测试
Bunny02122 小时前
SpringMVC笔记
java·redis·笔记
blammmp2 小时前
Java EE 进阶:Spring MVC(1)
spring·java-ee·mvc
架构文摘JGWZ2 小时前
FastJson很快,有什么用?
后端·学习
BinaryBardC2 小时前
Swift语言的网络编程
开发语言·后端·golang
feng_blog66882 小时前
【docker-1】快速入门docker
java·docker·eureka
邓熙榆2 小时前
Haskell语言的正则表达式
开发语言·后端·golang
枫叶落雨2224 小时前
04JavaWeb——Maven-SpringBootWeb入门
java·maven