深入理解Spring MVC开发-文件上传

前言

Spring MVC为文件上传提供了良好的支持,而在Spring Boot中可以更加简便的配置文件上传所需的内容。为了更好的理解Spring Boot的配置,首先从SPring MVC的机制谈起

1. Spring MVC对文件上传的支持

首先,DispatcherServlet会使用适配器模式,将HttpServletRequest接口对象转换成MultiPartHttpServletRequest对象。MultipartHttpServletRequest接口扩展了HttpServletRequest接口所有的方法,而且定义了一些操作文件的方法,这样通过这些方法就可以实现对文件上传的操作。
下面探讨HttpServletRequest和MultipartHttpServletRequest的关系,如图所示

在这里插入图片描述
这里对于文件上传的场景,Spring MVC会将HttpServletRequest对象转换为MultipartHttpServletRequest对象。从MultipartHttpServletRequest接口可以看出,它存在很多方法来处理文件,这样在Spring MVC中操作文件就非常便捷了。

只是使用Spring MVC上传文件时,还需要配置MultipartHttpServletRequest,这个任务是通过MultipartResolver接口实现的。对于MultipartResolver接口,他又存在两个实现按类,这两个实现类分别是StandardServletMultipartResolver和CommonMultipartResolver,可以使用他们中的任意一个来实现文件上传。

在默认情况腺癌Spring推荐使用的是StandardServletMultipartResolver,因为他只需要依赖Servlet API提供的包,而对于CommonMultipartResolver,则需要依赖Apache提供的第三方包来实现,这显然没有StandardServletMultipartResolver来的实在。从实用的角度来说,因为Spring 3.1之后就已经能够支持StandardServletMultipartREsolver,所以CommonMultipartResolver已经被渐渐废弃了,这里不再对其进行介绍。他们的关系图如下:
在这里插入图片描述
在Spring Boot机制中,如果你没定义MultipartResolver对象,那么自动配置的机制会为你自动创建MultipartResolver对象,实际为StandardServletMultipartResolver,所以你并不需要自己去创建他.为了更加灵活,Spring Boot提供一下代码所示的配置项目

spring:
  servlet:
    multipart:
      #是否启用多分部文件上传功能
      enabled: true
      #将文件写入磁盘的阙值
      file-size-threshold: 0
      max-file-size: 100000000 #限制单个文件大小
      #限制所有文件大小
      max-request-size: 100000000
      #是否延迟多部件文件请求的参数和文件的解析 
      resolve-lazily: false

根据这些配置Spring Boot会自动生成StandardServletMultipartResolver对象,这样就可以对上传的文件进行配置.对于文件的上传可以使用Servlet API提供的Part接口.也可以使用Spring MVC提供的MulyipartFile接口作为参数.其实无论使用哪一个类都是允许的,只是我更加推荐使用Part,因为毕竟MultipartFile是Spring MVC提供的第三方才能够进行支持的,后续版本变化的几率更大一些.

2. 开发文件上传功能.

开发Spring Boot下的MVC上传,首先需要配置代码清单中的配置项

spring:
  servlet:
    multipart:
      #是否启用多分部文件上传功能
      enabled: true
      #将文件写入磁盘的阙值
      file-size-threshold: 0
      max-file-size: 100000000 #限制单个文件大小
      #限制所有文件大小
      max-request-size: 100000000
      #是否延迟多部件文件请求的参数和文件的解析 
      resolve-lazily: false

这里不指定上传的文件夹,因为在实际开发中还是直接放到项目目录之中.单个文件大小爱哦100MB,所有文件大小最大100MB.为了测试文件上传需要编写HTML文件.

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8" http-equiv="Content-Type" content="text/html">
    <title>文件上传</title>
    <script src="https://code.jquery.com/jquery-3.2.0.js"></script>
</head>
<body>
    <form method="post" action="./request" enctype="multipart/form-data">
        <input type="file" name="file" value="请选择上传文件">
        <input type="submit" value="提交">
    </form>
</body>
</html>

请注意,这里的form表单声明为multipart/form-data,如果没有这个声明,Spring MVC就会解析文件出错,从而导致上传文件失败.有了HTML文件,下面开发文件上传控制器(这个控制器将包括使用HttpServletRequest, MultipartFile和Part参数)来完成文件上传.代码清单如下:

package cn.hctech2006.boot.bootmvc.controller;

@Controller
@RequestMapping("/file")
public class FileController {
    /**
     * 打开文件上传请求页面
     * @return
     */
    @GetMapping("/upload/page")
    public String uploadPage(){
        return "/role/upload";
    }
    @PostMapping("/upload/request")
    @ResponseBody
    public Map<String, Object> uploadRequest(HttpServletRequest request) throws FileNotFoundException {
        boolean flag = false;

        MultipartHttpServletRequest mreq = null;
        if(request instanceof MultipartHttpServletRequest){
            mreq = (MultipartHttpServletRequest) request;
        }else{
            return dealResultMap(false,"文件上传失败");
        }
        MultipartFile mf = mreq.getFile("file");
        String fileName = mf.getOriginalFilename();
        String url = ResourceUtils.getURL("").getPath()+fileName;
        File file = new File(url);
        try{
            mf.transferTo(file);
            return dealResultMap(true, "上传成功");
        }catch (Exception e){
            e.printStackTrace();
            return dealResultMap(false, "上传失败");
        }

    }
    @PostMapping("/upload/multipart")
    @ResponseBody
    public Map<String, Object> uploadMultipart(MultipartFile file) throws FileNotFoundException {
        boolean flag = false;
        String fileName = file.getOriginalFilename();
        String url = ResourceUtils.getURL("").getPath()+fileName;
        File folder = new File(url);
        try{
            file.transferTo(folder);
            return dealResultMap(true, "上传成功");
        }catch (Exception e){
            e.printStackTrace();
            return dealResultMap(false, "上传失败");
        }

    }
    @PostMapping("/upload/part")
    @ResponseBody
    public Map<String, Object> uploadPart(Part file) throws FileNotFoundException {
        boolean flag = false;
        String fileName = file.getSubmittedFileName();
        String url = ResourceUtils.getURL("").getPath()+fileName;
        try{
            file.write(url);
            return dealResultMap(true, "上传成功");
        }catch (Exception e){
            e.printStackTrace();
            return dealResultMap(false, "上传失败");
        }

    }
    private Map<String, Object> dealResultMap(boolean success, String msg){
        Map<String, Object> result = new HashMap<>();
        result.put("success",success);
        result.put("msg", msg);
        return  result;
    }
}

代码中的uploadPage方法用来映射上传文件的HTML,所以只需要请求他便能够打开上传文件的页面.uploadRequest方法则将HttpServletRequest对象传递.

从之前的分析可以知道,在调用控制器之前,DispatcherServlet会将器转换为MultipartHttpServletRequest对象,所以方法中使用了强制转换,从而得到MultipartHttpServletRequest对象,然后获取Multipart对象,截止使用MultipartFile对象的getOriginalFileName方法就可以得到上传的文件名,而通过他的transferTo方法,就可以将文件保存到对应的路径之中.

uploadMultipartFIle则是直接使用MultipartFile对象获取上传的文件,从而进行操作,uploadPart方法则是使用Servlet放入API,可以使用write方法直接写入文件,这也是推荐的.

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值