Spring Boot上传文件/图片&图片显示

一、文章前言

1. 本文章主要讲述如何在spring boot下上传文件,尤其是上传图片并显示,例如用户注册的时候上传了头像,此时头像会加载在注册页面上面,在Spring MVC的时候,这样实现还好实现,但是到了Spring Boot就并不是这样

2. 小伙伴也发现了,在使用部署到Tomcat服务器形式的项目,上传到的图片直接上传到Tomcat服务器中,都能访问,但是在Spring Boot中,内嵌的Tomcat,每次都是启动一个新的Tomcat,位置并不固定

3. 于是就带来了一个问题,第一次上传到了Tomcat中,能访问,但是一重启项目,Game Over

4. 所以本文章和大家一起学习下,如何在Spring Boot中指定文件上传路径和访问路径中的资源,这样就可以把保存图片和项目分开,独自管理

5. 文章中主要使用Spring Boot & Thymeleaf & Maven来演示,不会Thymeleaf的朋友不用担心,用的东西很少,和JSP差不多

二、环境搭建

2.1 Spring Boot的静态资源访问

1. 通常项目js、css、gif、html、xml、avi等文件都算是静态资源,静态资源的访问主要有两种方式:Spring Boot约定的目录、自己指定静态资源路径

2. Spring Boot约定的目录有四个,照存放路径约定,默认将会放到以下src/main/resources下的4个目录中

  • META-INF/resources
  • resources
  • static
  • public
  • 优先级:META-INF/resources > resources > static > public

3. 通常我们会放到static中,但是一般像图片、视频等资源都是分开存储,所以常常需要指定静态资源访问路径

4. 而自定义路径我们需要实现WebMvcConfigurer接口,然后覆写addResourceHandlers方法添加资源映射路径,需要调用registry的addResourceHandler("/**").addResourceLocations("classpath:/路径/")完成映射添加(对这个接口不熟悉的朋友建议先学习下,本篇文章主要是文件上传,不会对此借口做详细介绍),完成之后就可以将我们自己的目录映射为一个资源路径

5. 上传文件主要使用MultipartFile类完成,所以文件上传的两个核心就是MultipartFile类和WebMvcConfigurer接口

2.2 Spring Boot环境搭建

1. 有了以上简单的了解后,我们现在开始搭建Spring Boot环境,环境主要使用IDEA+Spring Initializr创建,相信都看到这篇文档了,相信创建项目以及是基本功,废话少说进入正题

2. 创建完成我们需要加入Thymeleaf的依赖,如果采用别的模板引擎,根据自己的情况添加

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

3. 打开application.properties配置文件(如果你是yml简单改一些就行),我们在配置文件中配置四个内容

  • 修改Tomcat端口(非必须,默认8080)
  • 配置Thymeleaf
  • 配置Spring MVC
  • 配置文件路径(在配置文件中配置比代码中写死要好)

4. 根据第三点我们配置application.properties的内容如下

  • user.file.path=自己想要保存文件的目录,默认不要忘了/或者\\
    user.file.name=文件上传名称,真实项目中可以动态生成,这里为了演示写死
配置Thymeleaf,模式、编码、不使用缓存
spring.thymeleaf.mode=HTML
spring.thymeleaf.encoding=UTF-8
spring.thymeleaf.cache=false
  • Spring MVC视图配置,相信大家很熟悉了,直接走
spring.mvc.view.prefix=/
spring.mvc.view.suffix=.html
# 修改服务器端口
server.port=8888
# Thymeleaf
spring.thymeleaf.mode=HTML
spring.thymeleaf.encoding=UTF-8
spring.thymeleaf.cache=false
# Spring MVC
spring.mvc.view.prefix=/
spring.mvc.view.suffix=.html
# 文件路径, 注意路径末尾一定要带上/
user.file.path=F:/img/
user.file.name=springboot.jpg

5. 配置完以上简单的项目框架算是有了,接下类我们开始实现

三、前端界面

1. 前端界面比较简单,就一个显示图片的img标签和一个上传文件的表单

2. 注意Thymeleaf中html文件需要方法resources的templates目录下,文件名index.html就行

3. 编写HTML

  • 在HTML标签上引入thymeleaf的名称空间:xmlns:th="http://www.thymeleaf.org"
  • 编写img标签,使用th语法指定img的资源路径:<img th:src="${filePath}">
  • 编写上传表单:这里比较简单,就不做介绍了,注意的是input为file的name需要记录,因为这个name必须要和控制器中MultipartFile的变量名相同,如果不同需要使用@RequestParam("file上传标签的name值")指定,截图和源码分别如下

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>index</title>
</head>
<body>
    <img th:src="${filePath}">
    <form action="upload" method="post" enctype="multipart/form-data">
        <input type="file" name="pic">
        <input type="submit">
    </form>
</body>
</html>

4. 简单启动项目,输入访问地址就可以看到下面简陋的东西~~

四、上传实现

1. 上传文件建立一个controller,把我们配置文件中指定的文件名和路径使用@Value注解注入进来

2. 在方法参数中指定MultipartFile,注意返回值使用了ModelAndView是为了图片显示的时候将值回传回去

  • 参数为@RequestParam("pic") MultipartFile multipartFile 或者 MultipartFile pic,注意这个pic和表单中的文件标签的name值一样
  • 创建一个文件File file = new File(filePath + multipartFile.getOriginalFilename());
  • 调用MultipartFile 的multipartFile.transferTo(file)保存文件即可,是不是很简单

/**
 * 上传文件控制器
 *
 * @param multipartFile 文件上传类
 * @return ModelAndView
 */
@RequestMapping("/upload")
public ModelAndView update(@RequestParam("pic") MultipartFile multipartFile) {

	try {
		// 保存图片
		File file = new File(filePath + multipartFile.getOriginalFilename());
		multipartFile.transferTo(file);
	} catch (IOException e) {
		e.printStackTrace();
	}

	ModelAndView modelAndView = new ModelAndView();
	modelAndView.setViewName("index");

	return modelAndView;
}

3. 启动项目,我们测试一下文件上传(此时还是文件上传,并非图片显示),选择文件,然后提交,比如此处上传一个Redis-Docker的脚本,上传完成后可以在配置文件中指定的目录下看到该文件证明上传成功,文件上传没有问题就开始上传图片并显示

五、显示实现

5.1 控制器方式实现

1. 控制器方式实现其实就是为图片格式指定一个请求,每次加载都请求类,/{filename:.+}是指定路径变量配货图片如xx.png格式这个请求,resourceLoader.getResource("file:" + Paths.get(filePath + filename))); 中的 "file:"开头的代表使用file此种类型去加载这个资源,因为HTML是不能直接访问本地资源的,需要将本地资源放到file类型告诉HTML这个可以访问

@RequestMapping(value = "/{filename:.+}")
@ResponseBody
public ResponseEntity<?> getFile(@PathVariable String filename) {
	try {
		return ResponseEntity.ok(resourceLoader.getResource("file:" + Paths.get(filePath + filename)));
	} catch (Exception e) {
		return ResponseEntity.notFound().build();
	}
}

2. 配置好之后在之前写的upload上传控制器中加入一项 modelAndView.getModel().put("filePath", "/" + fileName); filePath是给img标签中的thymeleaf加载使用的,包含了图片的路径,这里指定了“/”是指在项目根目录加载资源

3. 重新启动项目,运行选择一张图片上传就可以看到文件上传收可以显示

4. 但是这种方式不太喜欢,因为有可能有别的请求误请求到此请求上,所以推荐使用5.2的配置方式

5.2 配置方式实现(推荐)

1. 配置方式就是实现WebMvcConfigurer, 将配置文件中文件路径也当做项目的的静态资源路径,同内置的static、public约定文件夹一样,配置注意一下两个事项

  • 项目中的资源是使用classpath:/开头,而本地文件夹需要使用file:/ 开头,使用文件协议加载文件
  • 结尾一定要有/或者\\,推荐使用/,如果不加没效果
  • 配置截图和源码如下

@Component
public class CustomWebConfiguration implements WebMvcConfigurer {
    @Value("${user.file.path}")
    private String filePath;

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {

        // 注意如果filePath是写死在这里,一定不要忘记尾部的/或者\\,这样才能读取其目录下的文件
        registry.addResourceHandler("/**").addResourceLocations(
                "classpath:/META-INF/resources/",
                "classpath:/resources/",
                "classpath:/static/",
                "classpath:/public/",
                "file:/" + filePath,
                "classpath:/webapp/");
    }
}

2. 重新启动项目,上传图片名称为springboot.jpg的文件,可以自己在配置文件该,这里只是演示,然后就可以看到下面的效果,controller配置和此处配置选其一即可,推荐使用配置

3. 来一张动图

六、项目源码

项目源码放到了百度云盘,方便大家下载:

链接: https://pan.baidu.com/s/1Vh9b6ZKs5KzR4f6ltIX4oA 提取码: ww5x

有问题欢迎留言大家一起探讨学习

发布了118 篇原创文章 · 获赞 1115 · 访问量 213万+

猜你喜欢

转载自blog.csdn.net/sinat_34104446/article/details/100178488
今日推荐