一篇文章带你搞定 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
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章