前言

需要实现文件上传功能需要 MultipartResolver 接口的实现类的实例,这样才可以实现文件上传

MultipartResolver 有两个实现类:

  • StandardServletMultipartResolver:springboot 中以自动配置完成,直接使用即可
  • CommonsMultipartResolver:springmvc中使用的是CommonsMultipartResolver,需要在springmvc中配置其bean,其兼容性较好,也是传统ssm中使用

而在 MultipartAutoConfiguration 类中为 springboot 配置了其 StandardServletMultipartResolver的bean

@AutoConfiguration
@ConditionalOnClass({Servlet.class, StandardServletMultipartResolver.class, MultipartConfigElement.class})
@ConditionalOnProperty(
    prefix = "spring.servlet.multipart",
    name = {"enabled"},
    matchIfMissing = true
)
@ConditionalOnWebApplication(
    type = Type.SERVLET
)
@EnableConfigurationProperties({MultipartProperties.class})
public class MultipartAutoConfiguration {
    @Bean(
        name = {"multipartResolver"}
    )
    @ConditionalOnMissingBean({MultipartResolver.class})
    public StandardServletMultipartResolver multipartResolver() {
        StandardServletMultipartResolver multipartResolver = new StandardServletMultipartResolver();
        multipartResolver.setResolveLazily(this.multipartProperties.isResolveLazily());
        return multipartResolver;
    }
}

在配置文件中可以通过 spring.servlet.multipart. 来配置文件上传设置。

第一种 单文件上传

1、页面准备

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form action="/load" method="post" enctype="multipart/form-data">
    <input type="file" name="file">
    <input type="submit" value="上传">
</form>
</body>
</html>

在 from 表单中通过 enctype 来设置表单的数据构成,

multipart/form-data:是指表单数据有多部分构成,既有文本数据,又有文件等二进制数据的意思。

默认情况下,enctype 的值是 application/x-www-form-urlencoded,不能用于文件上传,只有使用了 multipart/form-data,才能完整的传递文件数据。

文件上传输入框中必须要有 name 属性,且控制器方法中的参数名也需和 name 属性值对应,否则传输到控制器中不存在。

2、控制器方法

@RestController
public class UploadFileController {
    //设置时间格式
    SimpleDateFormat sdf = new SimpleDateFormat("/yyyy/MM/dd/");
    @PostMapping("/load")
    public String upload(MultipartFile file, HttpServletRequest req){//参数名需要与form表单中设置的 name属性值对应上,否则获取到的为null
        //1、处理文件位置
        //文件存放位置
        String realPath = req.getServletContext().getRealPath("/");
        //按照时间格式划分
        String format = sdf.format(new Date());
        String path = realPath + format;
        //文件夹
        File folder = new File(path);
        //判断文件是否存在
        if (!folder.exists()){//不存在,则创建
            //这里需要使用mkdirs,因为为多层目录
            folder.mkdirs();
        }
        //2、处理文件名
        //获取文件后缀+文件名
        String oldName = file.getOriginalFilename();
        //将后缀加到新的文件名上
        String newName = UUID.randomUUID().toString() + oldName.substring(oldName.lastIndexOf("."));
        try {
            //文件保存
            file.transferTo(new File(folder,newName));
            //获取请求协议                            获取主机名                       获取端口
            String s = req.getScheme() + "://" + req.getServerName() + ":" + req.getServerPort() + format + newName;//文件的访问路径
            return s;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return "";
    }

}

第二种 多文件上传

方式一:一步多文件

1、页面准备

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form action="/load2" method="post" enctype="multipart/form-data">
    <input type="file" name="files" multiple>
    <input type="submit" value="上传">
</form>
</body>
</html>

在页面中将输入文件框中添加 mutiple 属性,表示可以上传多个文件

文件上传输入框中必须要有 name 属性,且控制器方法中的参数名也需和 name 属性值对应,否则传输到控制器中不存在。

2、控制器方法

@RestController
public class UploadFileController2 {
    //设置时间格式
    SimpleDateFormat sdf = new SimpleDateFormat("/yyyy/MM/dd/");
    @PostMapping("/load2")
    public void upload(MultipartFile[] files, HttpServletRequest req){//参数名需要与form表单中设置的 name属性值对应上,否则获取到的为null
        //1、处理文件位置
        //文件存放位置
        String realPath = req.getServletContext().getRealPath("/");
        //按照时间格式划分
        String format = sdf.format(new Date());
        String path = realPath + format;
        //文件夹
        File folder = new File(path);
        //判断文件是否存在
        if (!folder.exists()){//不存在,则创建
            //这里需要使用mkdirs,因为为多层目录
            folder.mkdirs();
        }
        try {
            for (MultipartFile file : files) {
                //2、处理文件名
                //获取文件后缀+文件名
                String oldName = file.getOriginalFilename();
                //将后缀加到新的文件名上
                String newName = UUID.randomUUID().toString() + oldName.substring(oldName.lastIndexOf("."));
                //文件保存
                file.transferTo(new File(folder, newName));
                //获取请求协议                            获取主机名                       获取端口
                String s = req.getScheme() + "://" + req.getServerName() + ":" + req.getServerPort() + format + newName;//文件的访问路径
                System.out.println("s = " + s);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

}

与单文件上传类似,不过在文件保存时,需要放在循环中,依次保存

异常捕获 与 循环同时存在时,需要将 循环放置于 异常捕获中,这样效率高一点

方式二:多步多文件

1、页面准备

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form action="/load3" method="post" enctype="multipart/form-data">
    <input type="file" name="file1">
    <input type="file" name="file2">
    <input type="submit" value="上传">
</form>
</body>
</html>

在页面中设置多个 文件上传框,来实现多文件上传

2、控制器方法

@RestController
public class UploadFileController3 {
    //设置时间格式
    SimpleDateFormat sdf = new SimpleDateFormat("/yyyy/MM/dd/");
    @PostMapping("/load3")
    public void upload(MultipartFile file1,MultipartFile file2, HttpServletRequest req){//参数名需要与form表单中设置的 name属性值对应上,否则获取到的为null
        //1、处理文件位置
        //文件存放位置
        String realPath = req.getServletContext().getRealPath("/");
        //按照时间格式划分
        String format = sdf.format(new Date());
        String path = realPath + format;
        //文件夹
        File folder = new File(path);
        //判断文件是否存在
        if (!folder.exists()){//不存在,则创建
            //这里需要使用mkdirs,因为为多层目录
            folder.mkdirs();
        }
        //2、处理文件名
        //获取文件后缀+文件名
        String oldName1 = file1.getOriginalFilename();
        //将后缀加到新的文件名上
        String newName1 = UUID.randomUUID().toString() + oldName1.substring(oldName1.lastIndexOf("."));
        try {
            //文件保存
            file1.transferTo(new File(folder,newName1));
            //获取请求协议                            获取主机名                       获取端口
            String s = req.getScheme() + "://" + req.getServerName() + ":" + req.getServerPort() + format + newName1;//文件的访问路径
            System.out.println("s = " + s);
        } catch (IOException e) {
            e.printStackTrace();
        }
        //2、处理文件名
        //获取文件后缀+文件名
        String oldName2 = file2.getOriginalFilename();
        //将后缀加到新的文件名上
        String newName2 = UUID.randomUUID().toString() + oldName2.substring(oldName2.lastIndexOf("."));
        try {
            //文件保存
            file2.transferTo(new File(folder,newName2));
            //获取请求协议                            获取主机名                       获取端口
            String s = req.getScheme() + "://" + req.getServerName() + ":" + req.getServerPort() + format + newName2;//文件的访问路径
            System.out.println("s = " + s);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}

在控制器方法中的参数,需要设置相同名称、数量的参数来与页面中文件上传框中对应

第三种 ajax文件上传

此方式也可进行多文件上传,方式与上述差不多。

1、页面准备

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://code.jquery.com/jquery-3.7.0.js" integrity="sha256-JlqSTELeR4TLqP0OG9dxM7yDPqX1ox/HfgiSLBj8+kM=" crossorigin="anonymous"></script>
</head>
<body>
<div id="result"></div>
<input type="file" id="file">
<input type="button" value="上传" onclick="fileUpLoad()">
<script>
   function fileUpLoad() {
       var file = $("#file")[0].files[0];
       var formData = new FormData();
       formData.append("file",file);
       $.ajax({
           type:'post',
           url:'/loadajax',
           processData:false,
           contentType:false,
           data:formData,
           success:function (msg){
                $("#result").html(msg);
           }
       })
   }
</script>
</body>
</html>

2、控制器方法

public class AjaxUploadFileController {
    //设置时间格式
    SimpleDateFormat sdf = new SimpleDateFormat("/yyyy/MM/dd/");
    @PostMapping("/loadajax")
    public String upload(MultipartFile file, HttpServletRequest req){//参数名需要与form表单中设置的 name属性值对应上,否则获取到的为null
        //1、处理文件位置
        //文件存放位置
        String realPath = req.getServletContext().getRealPath("/");
        //按照时间格式划分
        String format = sdf.format(new Date());
        String path = realPath + format;
        //文件夹
        File folder = new File(path);
        //判断文件是否存在
        if (!folder.exists()){//不存在,则创建
            //这里需要使用mkdirs,因为为多层目录
            folder.mkdirs();
        }
        //2、处理文件名
        //获取文件后缀+文件名
        String oldName = file.getOriginalFilename();
        //将后缀加到新的文件名上
        String newName = UUID.randomUUID().toString() + oldName.substring(oldName.lastIndexOf("."));
        try {
            //文件保存
            file.transferTo(new File(folder,newName));
            //获取请求协议                            获取主机名                       获取端口
            String s = req.getScheme() + "://" + req.getServerName() + ":" + req.getServerPort() + format + newName;//文件的访问路径
            return s;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return "";
    }

}
posted on 2023-06-15 16:02  xashould  阅读(3712)  评论(0编辑  收藏  举报