SpringMVC中文件的上传和下载

文件上传

文件的上传和下载都是项目开发中最常用的功能,例如头像的上传,图片的下载,附件文件的上传和下载等等

文件上传的概述

多数文件上传都是通过表单的形式提交给后台服务器的,因此要实现文件的上传功能,就需要提供一个文件上传的表单,并且该表单应该满足以下三个条件

  1. form表单的method属性设置为post
  2. form表单的enctype属性设置为multipart/form-data
  3. 提供input标签的文件上传输入框
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>文件上传</title>
</head>
<body>
<form action="update" method="post" enctype="multipart/form-data">
    <input type="file" name="fileName" multiple/>
    <input type="submit" value="文件上传">
</form>
</body>
</html>

注意,其中的multiple属性是HTML5中新增属性,如果选择了该属性,那么可以同时选择多个文件进行上传,即实现了多文件的上传

当客户端form表单的enctype属性为multipart/form-data的时候,浏览器就会采用二进制流的形式来处理表单数据,服务器端就会对文件上传的请求进行解析处理,SpringMVC对文件上传提供了直接的支持,这种支持是通过MUltipartResolver(多部件解析器)对象实现的

其中MUltipartResolver是一个借口对象,需要通过它的实现类CommonsMUltipartResolver来完成文件的上传工作,我们可以在配置文件中定义MUltipartResolver接口的Bean来实现接口

    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <!--设置请求编码格式,必须和JSP中的 pageEncoding属性一致,默认为ISO-8859-1-->
        <property name="defaultEncoding" value="UTF-8"/>
        <!--设置允许上传文件的最大值(2M),单位为字节-->
        <property name="maxUploadSize" value="2097152"/>
    </bean>

其中property对应表如下

属性名 解释
maxUploadSize 上传文件的最大长度,其中单位为字节
maxUploadSizePerFile 跟maxUploadSize差不多,不过maxUploadSizePerFile是限制每个上传文件的大小,而maxUploadSize是限制总的上传文件大小。
uploadTempDir 设置上传文件时的临时目录,默认是Servlet容器的临时目录。
defaultEncoding 表示用来解析request请求的默认编码格式,当没有指定的时候根据Servlet规范会使用默认值ISO-8859-1。当request自己指明了它的编码格式的时候就会忽略这里指定的defaultEncoding。
maxInMemorySize 设置在文件上传时允许写到内存中的最大值,以字节为单位计算,默认是10240。
resolveLazily 为true时,启用推迟文件解析,以便在UploadAction中捕获文件大小异常。

注意,因为MultipartResolver接口的实现类CommonsMultipartResolver内部是引用multipartResolver字符串来获取该实现类对象并完成文件解析的,所以在配置CommonsMultipartResolver时必须制定该Bean的id为multipartResolver

支持包的引入

本项目构建采用的是Maven,所以可以在pom.xml文件中引入如下配置

<!-- 上传组件包 -->
    <dependency>
      <groupId>commons-fileupload</groupId>
      <artifactId>commons-fileupload</artifactId>
      <version>1.3.1</version>
    </dependency>
    <dependency>
      <groupId>commons-io</groupId>
      <artifactId>commons-io</artifactId>
      <version>2.4</version>
    </dependency>
    <dependency>
      <groupId>commons-codec</groupId>
      <artifactId>commons-codec</artifactId>
      <version>1.9</version>
    </dependency>

如果你的项目没有采用maven构建,那么可以自行在apache官网进行下载所以需要的jar包

实现简单的文件上传

这个时候我们可以通过简单的修改,来进行我们程序的验证,首先我们应该修改我们的JSP文件

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>文件上传</title>
</head>
<body>
<form action="/upLoadFile" method="post" enctype="multipart/form-data">
    <input type="file" name="fileName" multiple/>
    <input type="submit" value="文件上传">
    上传是否成功:${msg}
</form>
</body>
</html>

我们可以看到,我们在form标签中新加入了一行${msg},这里是进行上传返回信息的显示的,之后我们在我们的controller包中新建一个FileController

package eendtech.controller;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;

/**
 * @ author Seale
 * @ Description: 文件上传
 * @ QQ:1801157108
 * @ Date 2019/4/14 14:51
 */
@Controller@RequestMapping(value = "/files")
public class FileController {
    @RequestMapping("/file")
    public String showFileJsp(){
        return "views/file.jsp";
    }

    @RequestMapping("/upLoadFile")
    public String handleFormUpload(@RequestParam("fileName") MultipartFile file,Model model){
        if (!file.isEmpty()){
            model.addAttribute("msg","success");
            return "views/file.jsp";
        }
        model.addAttribute("msg","failed");
        return "views/file.jsp";
    }

}

在这里我需要说明一下,MultipartFile接口类型的参数file,上传到程序中的文件就是被封装到该参数当中的,这个接口中提供了获取上传文件、文件名等方法,这些方法及其说明如下

方法 说明
String getName() 获取多部件form表单的参数名称
String getOriginalFilename() 获取上传文件的初始化名
String getContentType() 获取文件内容的类型
boolean isEmpty() 是否为空
long getSize() 取得文件的大小,单位是字节
byte[] getBytes() throws IOException 以字节数组的形式返回文件的内容,如果文件为空则抛出IO异常
InputStream getInputStream() throws IOException 读取文件的内容返回一个inputStream流
void transferTo(File dest) throws IOException, IllegalStateException 将上传文件保存到目标目录下

运行结果

比较完整的上传例子

进行修改

我们在简单案例的基础上进行修改,模拟一个网站的真实上传头像的案例

修改我们的JSP文件

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>文件上传</title>
    <script>
        function checkUpload() {
            var name = document.getElementById("name").value;
            var file = document.getElementById("file").value;
            if (name == ""){
                alert("请填写上传人");
                return false;
            }
            if (file.length==0 || file==""){
                alert("请选择你要上传的文件");
                return false;
            }
            return true;
        }
    </script>
</head>
<body>
<form action="${pageContext.request.contextPath}/files/upLoadFileForFinal" method="post" enctype="multipart/form-data" onsubmit="return checkUpload()">
    <input id="name" type="text" name="name" placeholder="上传人的姓名"> <br>
    <input id="file" type="file" name="fileName" multiple/>
    <input type="submit" value="文件上传">
    上传是否成功:${msg}
</form>
</body>
</html>

修改我们的controller文件

package eendtech.controller;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.UUID;

/**
 * @ author Seale
 * @ Description: 文件上传
 * @ QQ:1801157108
 * @ Date 2019/4/14 14:51
 */
@Controller@RequestMapping(value = "/files")
public class FileController {
    @RequestMapping("/file")
    public String showFileJsp(){
        return "views/file.jsp";
    }

    @RequestMapping("/upLoadFile")
    public String handleFormUpload(@RequestParam("fileName") MultipartFile file,Model model){
        if (!file.isEmpty()){
            model.addAttribute("msg","success");
            return "views/file.jsp";
        }
        model.addAttribute("msg","failed");
        return "views/file.jsp";
    }
    @RequestMapping("/upLoadFileForFinal")
    public String handleFormUploadForFinal(@RequestParam("name") String name
            , @RequestParam("fileName") List<MultipartFile> fileList
            , Model model, HttpServletRequest request){
        //判断所厂商的文件是否存在
        if (!fileList.isEmpty() && fileList.size() > 0){
            //循环输出上传的文件
            for (MultipartFile file :fileList) {
                //获取上传文件的原始名称
                String originalFileName = file.getOriginalFilename();
                System.out.println("当前文件的名称:"+originalFileName);
                //设置上传文件的保存地址
                String dirPath = request.getServletContext().getRealPath("/upLoad/");
                File filePath = new File(dirPath);
                System.out.println("当前文件的保存地址:"+dirPath);
                System.out.println("--------------------------");
                if (!filePath.exists()){
                    //mkdirs会自动建立多级目录;mkdir只能建立一级目录,如果目录中包含多级目录,且当前目录不存在则返回false
                    filePath.mkdirs();
                }
                //使用UUID重新命名上传的文件名称(上传人_uuid_原始名称)
                String newFileName = name+"_"+ UUID.randomUUID()+"_"+originalFileName;

                try {
                    //使用MultipartFile接口的方法完成文件上传到指定目录
                    file.transferTo(new File(dirPath+newFileName));
                } catch (IOException e) {
                    e.printStackTrace();
                    model.addAttribute("msg","上传失败");
                    return "views/file.jsp";
                }
            }
            model.addAttribute("msg","上传成功");
            return "views/file.jsp";
        }else{
            model.addAttribute("msg","上传失败");
            return "views/file.jsp";
        }
    }

}

运行效果



本作品采用知识共享署名 4.0 国际许可协议进行许可。

如果可以的话,请给我钱请给我点赞赏,小小心意即可!

Last modification:April 14, 2019
If you think my article is useful to you, please feel free to appreciate