Spring Boot 技术探索

Spring Boot makes it easy to create stand-alone, production-grade Spring based Applications that you can "just run".

18、Spring Boot中文件的上传

平台环境:

名称

版本号

Mac OS X

10.14.6

JDK

1.8.0_201

Apache Maven

3.6.0

IntelliJ IDEA

2019.1 (Ultimate Edition)

Spring Boot

2.1.7.RELEASE

 

  文件上传是交互网站常见的功能之一,本次介绍的是传统的form表单上传文件,然后保存到服务器硬盘上的过程。

  除此之外,文件上传的形式还有:

  • AJAX上传(无刷新)
  • Flash与H5上传(支持上传进度和大文件上传)
  • 截图粘贴上传
  • 拖拽上传(新一点的浏览器才支持)

 

例子:

pom.xml加入依赖项

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>

 

在配置文件中增加配置项

# 支持的最大文件
spring.servlet.multipart.max-file-size=100MB
# 文件请求最大限制
spring.servlet.multipart.max-request-size=100MB


#是否允许multipart上传(默认true)
#spring.servlet.multipart.enabled=true


#将文件写入磁盘的阈值
#spring.servlet.multipart.file-size-threshold=0


#上传文件的临时目录
#spring.servlet.multipart.location=


#是否在文件或参数访问时,懒加载解析multipart请求(默认false)。
#spring.servlet.multipart.resolve-lazily=false

以上配置对应的配置类是org.springframework.boot.autoconfigure.web.servlet.MultipartProperties

 

修改启动类

package com.example.demo;


import org.apache.coyote.http11.AbstractHttp11Protocol;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.embedded.tomcat.TomcatConnectorCustomizer;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.context.annotation.Bean;


@SpringBootApplication
public class DemoApplication
{
    public static void main(String[] args)
    {
        SpringApplication.run(DemoApplication.class, args);
    }


    // 解决Tomcat遇到大文件出现连接被重置的问题
    @Bean
    public TomcatServletWebServerFactory tomcatEmbedded()
    {
        TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory();
        tomcat.addConnectorCustomizers((TomcatConnectorCustomizer) connector ->
        {
            if ((connector.getProtocolHandler() instanceof AbstractHttp11Protocol<?>))
            {
                // -1 意思是不限制
                ((AbstractHttp11Protocol<?>) connector.getProtocolHandler()).setMaxSwallowSize(-1);
            }
        });
        return tomcat;
    }
}

经过测试:这个不起作用,照样出现连接被重置的问题。

 

新建上传页面upload.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>Spring Boot file upload example</h1>
    <form method="POST" action="/uploadFile" enctype="multipart/form-data">
        <input type="file" name="file" /><br/><br/>
        <input type="submit" value="Submit" />
    </form>
</body>
</html>

 

新建上传成功后的跳转页uploadStatus.html

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>Spring Boot - Upload Status</h1>
    <div th:if="${message}">
        <h2 th:text="${message}"/>
    </div>
</body>
</html>

 

新建上传controller类

package com.example.demo.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.multipart.MultipartFile;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;


import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;


@Controller
public class UploadController
{
    // 上传文件存放的路径
    private static String UPLOADED_FOLDER = "/Users/wang/Downloads/";


    @GetMapping("/upload")
    public String index()
    {
        return "upload";
    }


    @PostMapping("/uploadFile")
    public String singleFileUpload(@RequestParam("file") MultipartFile file, RedirectAttributes redirectAttributes)
    {
        if (file.isEmpty() && file.getName().equals(""))
        {
            // file.getName().equals("")的目的是解决例如一个文本文件无任何内容0KB的情况,无法上传的BUG
            redirectAttributes.addFlashAttribute("message", "请选择要上传的文件");
            return "redirect:uploadStatus";
        }
        try
        {
            // Get the file and save it somewhere
            byte[] bytes = file.getBytes();
            // UPLOADED_FOLDER 文件本地存储地址
            Path path = Paths.get(UPLOADED_FOLDER + file.getOriginalFilename());
            Files.write(path, bytes);


            redirectAttributes.addFlashAttribute("message", "文件已成功上传 '" + file.getOriginalFilename() + "'");
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
        return "redirect:/uploadStatus";
    }


    @GetMapping("/uploadStatus")
    public String uploadStatus()
    {
        return "uploadStatus";
    }
}

Spring MVC会自动把浏览器请求中POST的文件封装到MultipartFile中,我们需要做的只是把文件保存到硬盘中即可。

 

加入全局异常捕获

package com.example.demo.controller;


import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.multipart.MultipartException;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;


@ControllerAdvice
public class GlobalExceptionHandler
{
    @ExceptionHandler(MultipartException.class)
    public String handleError1(MultipartException e, RedirectAttributes redirectAttributes)
    {
        redirectAttributes.addFlashAttribute("message", e.getCause().getMessage());
        return "redirect:/uploadStatus";
    }
}

由于之前启动类中“解决Tomcat遇到大文件出现连接被重置的问题”的代码未能生效,因此这里全局捕获到异常之后的跳转未能看到效果。

 

启动项目,访问http://localhost:8080/upload

选择文件,点submit之后,提示

Spring Boot - Upload Status
文件已成功上传 'test2.txt'

 


 

接下来在上面代码的基础上,增加多个文件同时上传的功能。

 

新建文件uploadMore.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>Spring Boot file upload example</h1>


    <form method="POST" action="/uploadMoreFile" enctype="multipart/form-data">
        文件1: <input type="file" name="file" /><br/><br/>
        文件2: <input type="file" name="file" /><br/><br/>
        文件3: <input type="file" name="file" /><br/><br/>
        <input type="submit" value="Submit" />
    </form>
</body>
</html>

 

在UploadController中,增加以下代码。

@GetMapping("/uploadMore")
public String uploadMore()
{
    return "uploadMore";
}


@PostMapping("/uploadMoreFile")
public String moreFileUpload(@RequestParam("file") MultipartFile[] files, RedirectAttributes redirectAttributes)
{
    if (files.length==0)
    {
        redirectAttributes.addFlashAttribute("message", "请选择要上传的文件");
        return "redirect:uploadStatus";
    }
    for(MultipartFile file:files)
    {
        try
        {
            byte[] bytes = file.getBytes();
            Path path = Paths.get(UPLOADED_FOLDER + file.getOriginalFilename());
            Files.write(path, bytes);
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
    }
    redirectAttributes.addFlashAttribute("message", "文件已全部上传完毕");
    return "redirect:/uploadStatus";
}

 

启动项目,访问http://localhost:8080/uploadMore

选择文件,点submit之后,提示

Spring Boot - Upload Status
文件已全部上传完毕

 

 

Bootstrap Thumbnail Second
MySQL

MySQL is the world's most popular open source database.

GO

Bootstrap Thumbnail Third
算法基础

本书介绍了什么是计算机算法,如何描述它们,以及如何来评估它们。

GO