[SpringBoot]单文件上传实例(Thymeleaf)

前言
文件上传对于互联网行业中是一个高频的场景,
Spring Boot 利用 MultipartFile 的特性来接收和处理上传的文件,

项目目录可以参考:[SpringBoot]项目初始化目录结构

项目目录

添加坐标到pom.xml:

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.5.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <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>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

在resources目录下的 application.yml 中添加配置:

application:
  #文件上传路径
  profile: E:/temp/
  #静态资源对外暴露的访问路径
  staticAccessPath: /temp/**
spring:
  thymeleaf:
    cache: false
  servlet:
    multipart:
      max-file-size: 10MB
      max-request-size: 10MB

经过上面的配置,我们就可以专注的开始代码的编写了。
Thymeleaf模板后缀用的是.html,我们把他放到 templates 目录下

上传文件表单页 upload.html :

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<body>

<h1>单文件上传实例</h1>
<form method="POST" action="/upload" 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">
<body>

<h1>上传状态</h1>

<div th:if="${message}">
    <h2 th:text="${message}"/>
    <img th:src="${imgUrl}">
</div>

</body>
</html>

SpringBoot项目中只允许有一个main方法,这个方法放在启动类当中

在 UploadApplication启动类 中添加一个tomcatEmbedded()方法:

@SpringBootApplication
public class UploadApplication {
    public static void main(String[] args) {
        SpringApplication.run(UploadApplication.class, args);
    }
    //Tomcat large file upload connection reset
    @Bean
    public TomcatServletWebServerFactory tomcatEmbedded() {
        TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory();
        tomcat.addConnectorCustomizers((TomcatConnectorCustomizer) connector -> {
            if ((connector.getProtocolHandler() instanceof AbstractHttp11Protocol<?>)) {
                //-1 means unlimited
                ((AbstractHttp11Protocol<?>) connector.getProtocolHandler()).setMaxSwallowSize(-1);
            }
        });
        return tomcat;
    }
}

TomcatServletWebServerFactory() 方法主要是为了解决上传文件大于 10M (上面所设置)出现连接重置的问题,此异常内容 GlobalException 也捕获不到

全局异常捕获GlobalExceptionHandler:

@ControllerAdvice
public class GlobalExceptionHandler {

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

设置一个 @ControllerAdvice 来监控Multipart的异常。并反馈给前端页面

控制层 UploadController :

@Controller
public class UploadController {

//    本地路径
    @Value("${application.profile}")
    private String profile ;
//    对外虚拟路径
    @Value("${application.staticAccessPath}")
    private String staticAccessPath ;

//    添加Thymeleaf模板的映射
    @GetMapping("/")
    public String index(){
        return "upload";
    }
    @GetMapping("/upload")
    public String getupload(RedirectAttributes redirect){
        redirect.addFlashAttribute("message","No file!"+profile);
        return "redirect:/uploadStatus";
    }
    @GetMapping("/uploadStatus")
    public String uploadStatus(){
        return "uploadStatus";
    }
//    上传文件的post请求
    @PostMapping("/upload")
    public String upload(@RequestParam("file") MultipartFile file , RedirectAttributes redirect){
        if (file.isEmpty()){
            redirect.addFlashAttribute("message","No file!");
            return "redirect:uploadStatus";
        }else {
            try{
                byte[] filebytes = file.getBytes();
//                Path path = Paths.get("/upLoad/"+file.getName());
                InputStream stream = file.getInputStream();
                String newFileName = MD5.calcMD5(stream);
                String type[] = file.getContentType().split("/");
                Path path = Paths.get(profile +newFileName+"."+type[1]);
                Files.write(path,filebytes);
                redirect.addFlashAttribute("message","Up load successful! The file name is "+newFileName+"."+type[1]);
                redirect.addFlashAttribute("imgUrl",staticAccessPath.replace("**",newFileName+"."+type[1]) );
            }catch (IOException e){
                e.printStackTrace();
            }
        }
        return "redirect:uploadStatus";
    }

}

一定要添加Thymeleaf模板的映射,否则会报404。

再添加一个配置,一个工具类
配置类AppConfigurer :用于映射本地文件到虚拟路径

@Configuration
public class AppConfigurer implements WebMvcConfigurer {
    //    本地路径
    @Value("${application.profile}")
    private String profile ;
    //    对外虚拟路径
    @Value("${application.staticAccessPath}")
    private String staticAccessPath ;

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler(staticAccessPath).addResourceLocations("file:"+profile);
    }
}

MD5工具类参考:[SpringBoot]获取上传文件的MD5值

实现效果:


表单页

状态页
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

友情链接更多精彩内容