SpringMVC_实现文件上传下载

6. SpringMVC实现文件上传下载

6.1. 文件上传细节分析

6.1.1. 文件上传的3要素
  1. form表单的 enctype取值必须是:multipart/form-data

    (默认值是:application/x-www-form-urlencoded)

    enctype:是表单请求正文的类型

  2. method属性取值必须是 Post

  3. 提供一个文件选择域

HTTP协议中新增的rfc1867协议,为 http 协议添加了上传功能。

根据 rfc1867协议规范,enctype=“multipart/form-data”, method=post, type=“file” 。这三个属性是必须的。multipart/form-data 是新增的编码类型,以提高二进制文件的传输效率。

  • enctype属性值

    enctype 属性规定在发送到服务器之前应该如何对表单数据进行编码。

描述
application/x-www-form-urlencoded 默认值。在发送前对所有字符进行编码为名称/值对
(将空格转换为 “+” 符号,特殊字符转换为 ASCII HEX 值)。
multipart/form-data 不对字符编码。在使用包含文件上传控件的表单时,必须使用该值。
text/plain 空格转换为 “+” 加号,但不对特殊字符编码。
6.1.2. 文件上传流程
  1. 客户端的浏览器,如 Microsoft IE, Mozila Firefox, Chrome 等,按照此规范将用户指定的文件发送到服务器端的网页程序。
  2. 服务器端的网页程序,如 php, asp, jsp 等,可以按照此规范,解析出用户发送来的文件。经过编码发送给服务器。
  3. http server ,例如 tomcat ,已经支持此协议,可接收发送来的文件。
    在这里插入图片描述
6.1.4. 第三方工具

文件上传过程比较复杂,但方式是固定的,因此出现了很多第三方的 http upload file 工具库,我们使用 Commons-fileupload 组件实现文件上传,需要导入该组件相应的支撑 jar 包:

  • Commons-fileupload
  • commons-io

commons-io 不属于文件上传组件的开发 jar 文件,但Commons-fileupload 组件从 1.1 版本开始,它

工作时需要 commons-io 包的支持。

使用maven依赖导入commons-fileupload依赖即可,commons-io会自动导入

<!--文件上传-->
<!-- https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload -->
<dependency>
    <groupId>commons-fileupload</groupId>
    <artifactId>commons-fileupload</artifactId>
    <version>1.4</version>
</dependency>

6.2. 文件上传

  1. 添加上传的jsp
  2. 配置文件上传解析器
  3. 编写controller完成上传
    在这里插入图片描述
6.2.1. 上传的jsp页面
  • upload.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>文件上传</title>
</head>
<body>

    <form action="/upload.do" method="post" enctype="multipart/form-data">
        名称:<input type="text" name="picname"/><br/>
        图片:<input type="file" name="uploadFile"/><br/>
        <input type="submit" value="上传"/>
    </form>

</body>
</html>
6.2.2. 配置文件解析器

springmvc.xml添加文件上传的解析器

<!-- 配置文件上传解析器 -->
<!-- id 的值是固定的-->
<bean id="multipartResolver"
      class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
    <!-- 设定文件上传的最大值为5MB,5*1024*1024 -->
    <property name="maxUploadSize" value="5242880"></property>
</bean>

6.2.3. controller完成文件上传

  1. 获取上传的文件名称
  2. 修改文件名,防止文件重名冲突
  3. 以日期区分保存文件的文件夹
  4. 将上传的文件保存到文件夹
 //注意MultipartFile变量名必须和form表单的file的name属性一致
@RequestMapping("/upload")
public String uploadFile(String picname, MultipartFile uploadFile,
                         HttpServletRequest request) throws IOException {
    if(uploadFile == null){
        return "error";
    }
    //保存文件名
    String fileName = "";

    //1.获取原始文件名
    String originalFilename = uploadFile.getOriginalFilename();
    //文件扩展名
    String suffix = originalFilename.substring(originalFilename.lastIndexOf("."));
    //把文件加上随机数,防止重名被覆盖
    String uuid = UUID.randomUUID().toString().replace("-", "").toUpperCase();
	//2. 修改文件名,防止文件重名冲突
    //文件名 = UUID_输入的文件名.扩展名  /   UUID_原文件名.扩展名
    //判断是否输入文件名
    if(!StringUtils.isEmpty(picname)){
        fileName = uuid+"_"+picname+suffix;
    }else {
        fileName = uuid+"_"+originalFilename;
    }
    System.out.println(fileName);

    //3. 以日期区分保存文件的文件夹
    //3.1.获取文件路径
    ServletContext servletContext = request.getSession().getServletContext();
    String basePath = servletContext.getRealPath("/upload");
    //3.2.按日期创建文件夹,避免一个文件夹文件过多
    String datePath = new SimpleDateFormat("yyyy-mm-dd").format(new Date());
    //3.3.拼接存放文件的文件夹路径
    File dir = new File(basePath + "/" + datePath);
    //3.4.判断文件夹是否存在,不存在则创建目录
    if (!dir.exists()){
        dir.mkdir();
    }
    //4.将上传的文件保存到文件夹
    //使用 MulitpartFile 接口中方法,把上传的文件写到指定位置
    uploadFile.transferTo(new File(dir,fileName));

    return "success";
}
  • 图片被上传到服务器指定位置
    在这里插入图片描述

6.3. 文件下载

文件下载步骤:

  1. 准备下载页面
  2. 实现文件下载方法
6.3.1. 下载页面

download.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>文件下载</title>
</head>
<body>
    <a href="/download?filename=年轻的我.jpg">年轻的我</a>
</body>
</html>
6.3.2. 下载方法
@RequestMapping("/download")
public String download(String filename, HttpServletResponse response){
    //没有下载的文件名可能是非法访问,直接返回null
    if(StringUtils.isEmpty(filename)){
        return null;
    }
    System.out.println("用户要下载的文件:"+filename);
    //服务器存放的源文件
    File sourceFile = new File("H:\\upload\\2020-07-27\\照片.jpg");

    //数据写入到byte数组
    byte[] bytes = null;
    FileInputStream inputStream = null;
    OutputStream outputStream =  null;
    try {
        //将下载的文件通过输入流读取
        inputStream = new FileInputStream(sourceFile);
        //创建写出数据的字节数组
        bytes = new byte[inputStream.available()];
        //将输入流数据转成字节
        inputStream.read(bytes);

        //下载的响应头header中只支持ASCII,文件名需要进行编码,否则下载不显示文件名
        filename = URLEncoder.encode(filename,"utf-8");
        //设置文件下载的响应头
        response.setHeader("Content-Disposition","attachment;filename="+filename);
        outputStream = response.getOutputStream();
        //将数据写出
        outputStream.write(bytes);
        //刷新缓冲区
        outputStream.flush();
    } catch (IOException e) {
        e.printStackTrace();
        throw new RuntimeException("文件下载异常!");
    }finally {
        //关闭输入流
        if(inputStream != null){
            try {
                inputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        //关闭输出流
        try {
            outputStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    return null;
}

猜你喜欢

转载自blog.csdn.net/qq_44509920/article/details/107700652
今日推荐