SpringBoot——Web开发

5.5 文件上传

文件上传的章节,之前在学Spring还是JavaWeb的时候,用JSP写过

5.5.1 文件上传

那么,SpringBoot怎么实现文件上传呢?

知识点:
1、文件上传,必须得用表单form来提交。
2、提交的表单必须要是post请求。get请求能提交的文件太小啦!!!
3、form表单必须有属性enctype="multipart/form-data"属性
4、单文件上传,直接用input标签,type为file
5、多文件上传,也用input标签,type也是file,但是要多一个multiple属性。

首先,我们写一个显示页面:
upload.html:

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>文件上传演示</title>
</head>
<body>
    <!--
        上传的表单必须是post请求
        而且必须有enctype="multipart/form-data"属性,服务器才知道这是文件上传请求
    -->
    <form th:action="@{/upload}" enctype="multipart/form-data" method="post">
        用户名:<input type="text" name="username"/><br>
        <!--单文件上传,type直接写file-->
        头  像:<input type="file" name="headImg"/><br>
        <!--多文件上传加multiple属性-->
        生活照:<input type="file" name="photos" multiple><br>
        <input type="submit" value="上传">
    </form>
</body>
</html>

然后我们写我们的控制器方法,一个用来跳转到upload.html页面,一个用来处理上传过来的文件。

知识点:
1、提交过来的普通数据,我们只需要用@RequestParam注解加他的name直接获取即可。
2、提交过来的单文件,我们用@RequestPart注解加他的name获取,用MultipartFile对象接收。
3、提交过来的多个文件,我们用@RequestPart注解加他的name获取,用MultipartFile[]数组对象接收。

UploadController.java代码如下:

package com.example.boot.controller;

import org.springframework.stereotype.Controller;
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.RequestPart;
import org.springframework.web.multipart.MultipartFile;

@Controller
public class UploadController {

	//将请求转发到upload.html页面
    @GetMapping("/upload")
    public String toUpload(){
        return "upload";
    }

	//接收提交的数据信息
    @PostMapping("/upload")
    public String receiveFile(@RequestParam("username") String username,
                              @RequestPart("headImg") MultipartFile headerImg,
                              @RequestPart("photos") MultipartFile[] photos){
        System.out.println("username="+username);
        System.out.println("headImg="+headerImg);
        System.out.println("photos="+photos);
        return "success";
    }
}

运行:

我们在头像传入一个图片,在生活照传入n个图片(多了可能会爆,所以我传了两张)

springboot上传excel到resouce目录 springboot表单文件上传_spring boot


如果传入的文件太多,导致上传的字节数大于1048576字节(也就是1MB)的话,会直接报500错误。

springboot上传excel到resouce目录 springboot表单文件上传_spring_02


所以我们暂时先传两个小图片,然后点击上传,跳转到success.html页面,后台输出:

springboot上传excel到resouce目录 springboot表单文件上传_spring_03

5.5.2 文件解析

我们将控制器方法的代码修改为:
直接这么拿肯定是不行滴!我们既然拿到图片了,那肯定要把他放到我们的服务器啊(虽然我没有,那就放本地咯)。

@PostMapping("/upload")
    public String receiveFile(@RequestParam("username") String username,
                              @RequestPart("headImg") MultipartFile headerImg,
                              @RequestPart("photos") MultipartFile[] photos) throws IOException {
        System.out.println("username="+username);
        System.out.println("headImg="+headerImg);
        System.out.println("photos="+photos);
        //判断文件是否为空,非空则保存到服务器或自己的磁盘
        if(! headerImg.isEmpty()){
            //获取文件原始名称
            String headImgName = headerImg.getOriginalFilename();
            headerImg.transferTo(new File(("D:\\img\\"+headImgName)));
        }
        System.out.println(photos.length);
        //判断文件数组是否有文件,有则遍历保存到服务器或磁盘
        if (photos.length > 0){
            for (MultipartFile photo : photos) {
                if(! photo.isEmpty()){
                    String photoName = photo.getOriginalFilename();
                    photo.transferTo(new File(("D:\\img\\"+photoName)));
                }
            }
        }
        return "success";
    }

运行结果:

springboot上传excel到resouce目录 springboot表单文件上传_上传_04


点击上传后,我们到D盘的img目录下:(文件都过来了)

springboot上传excel到resouce目录 springboot表单文件上传_上传_05

5.5.3 修改默认文件上传最大值

前面,我们提到了如果传过去的文件太大的话,那么服务器会报错500.

springboot上传excel到resouce目录 springboot表单文件上传_spring_02


那么,我们如果一定要传大图片怎么搞呢?简单,修改一下我们的默认配置就好了。在application.yml中使用spring.servlet.multipart.max-file-size:直接设置即可。

spring:
  servlet:
    multipart:
      max-file-size: 10MB

我们还可以配置我们默认上传的整个请求的最大值。使用spring.servlet.multipart.max-request-size

spring:
  servlet:
    multipart:
      max-file-size: 10MB
      max-request-size: 20MB

5.5.4 服务器怎么判断请求是不是文件上传请求

其实很简单,偷看一下源码:

通过判断请求头的ContentType的前缀是不是multipart/,就可以判断他是不是文件上传请求。(为什么不是判断multipart/form-data,因为源码中this.strictServletCompliance的默认值是false。)

public boolean isMultipart(HttpServletRequest request) {
        return StringUtils.startsWithIgnoreCase(request.getContentType(), this.strictServletCompliance ? "multipart/form-data" : "multipart/");
    }

文件上传请求的Content-Type,里面有我们在form表单写的multipart/form-data。

springboot上传excel到resouce目录 springboot表单文件上传_spring boot_07