利用SpirngBoot实现文件上传功能

零、本篇要点

  • 介绍SpringBoot对文件上传的自动配置。
  • 介绍MultipartFile接口。
  • 介绍SpringBoot+Thymeleaf文件上传demo的整合。
  • 介绍对文件类型,文件名长度等判断方法。

一、SpringBoot对文件处理相关自动配置

自动配置是SpringBoot为我们提供的便利之一,开发者可以在不作任何配置的情况下,使用SpringBoot提供的默认设置,如处理文件需要的MultipartResolver。

@Configuration(proxyBeanMethods = false)
@ConditionalOnClass({ Servlet.class, StandardServletMultipartResolver.class, MultipartConfigElement.class })
@ConditionalOnProperty(prefix = "spring.servlet.multipart", name = "enabled", matchIfMissing = true)
@ConditionalOnWebApplication(type = Type.SERVLET)
@EnableConfigurationProperties(MultipartProperties.class)
public class MultipartAutoConfiguration { private final MultipartProperties multipartProperties; public MultipartAutoConfiguration(MultipartProperties multipartProperties) {
this.multipartProperties = multipartProperties;
} @Bean
@ConditionalOnMissingBean({ MultipartConfigElement.class, CommonsMultipartResolver.class })
public MultipartConfigElement multipartConfigElement() {
return this.multipartProperties.createMultipartConfig();
} @Bean(name = DispatcherServlet.MULTIPART_RESOLVER_BEAN_NAME)
@ConditionalOnMissingBean(MultipartResolver.class)
public StandardServletMultipartResolver multipartResolver() {
StandardServletMultipartResolver multipartResolver = new StandardServletMultipartResolver();
multipartResolver.setResolveLazily(this.multipartProperties.isResolveLazily());
return multipartResolver;
} }
  • Spring3.1之后支持StandardServletMultipartResolver,且默认使用StandardServletMultipartResolver,它的优点在于:使用Servlet所提供的功能支持,不需要依赖任何其他的项目。
  • 想要自动配置生效,需要配置spring.servlet.multipart.enabled=true,当然这个配置默认就是true。
  • 相关的配置设置在MultipartProperties中,其中字段就是对应的属性设置,经典字段有:
    • enabled:是否开启文件上传自动配置,默认开启。
    • location:上传文件的临时目录。
    • maxFileSize:最大文件大小,以字节为单位,默认为1M。
    • maxRequestSize:整个请求的最大容量,默认为10M。
    • fileSizeThreshold:文件大小达到该阈值,将写入临时目录,默认为0,即所有文件都会直接写入磁盘临时文件中。
    • resolveLazily:是否惰性处理请求,默认为false。
  • 我们也可以自定义处理的细节,需要实现MultipartResolver接口。

二、处理上传文件MultipartFile接口

SpringBoot为我们提供了MultipartFile强大接口,让我们能够获取上传文件的详细信息,如原始文件名,内容类型等等,接口内容如下:

public interface MultipartFile extends InputStreamSource {
String getName(); //获取参数名
@Nullable
String getOriginalFilename();//原始的文件名
@Nullable
String getContentType();//内容类型
boolean isEmpty();
long getSize(); //大小
byte[] getBytes() throws IOException;// 获取字节数组
InputStream getInputStream() throws IOException;//以流方式进行读取
default Resource getResource() {
return new MultipartFileResource(this);
}
// 将上传的文件写入文件系统
void transferTo(File var1) throws IOException, IllegalStateException;
// 写入指定path
default void transferTo(Path dest) throws IOException, IllegalStateException {
FileCopyUtils.copy(this.getInputStream(), Files.newOutputStream(dest));
}
}

三、SpringBoot+Thymeleaf整合demo

1、编写控制器

/**
* 文件上传
*
* @author Summerday
*/
@Controller
public class FileUploadController { private static final String UPLOADED_FOLDER = System.getProperty("user.dir"); @GetMapping("/")
public String index() {
return "file";
} @PostMapping("/upload")
public String singleFileUpload(@RequestParam("file") MultipartFile file,
RedirectAttributes redirectAttributes) throws IOException { if (file.isEmpty()) {
redirectAttributes.addFlashAttribute("msg", "文件为空,请选择你的文件上传");
return "redirect:uploadStatus"; }
saveFile(file);
redirectAttributes.addFlashAttribute("msg", "上传文件" + file.getOriginalFilename() + "成功");
redirectAttributes.addFlashAttribute("url", "/upload/" + file.getOriginalFilename());
return "redirect:uploadStatus";
} private void saveFile(MultipartFile file) throws IOException {
Path path = Paths.get(UPLOADED_FOLDER + "/" + file.getOriginalFilename());
file.transferTo(path);
} @GetMapping("/uploadStatus")
public String uploadStatus() {
return "uploadStatus";
}
}

2、编写页面file.html

<html xmlns:th="http://www.thymeleaf.org">
<!--suppress ALL-->
<html lang="en">
<head>
<meta charset="UTF-8">
<title>文件上传界面</title>
</head>
<body>
<div>
<form method="POST" enctype="multipart/form-data" action="/upload">
<table>
<tr><td><input type="file" name="file" /></td></tr>
<tr><td></td><td><input type="submit" value="上传" /></td></tr>
</table>
</form> </div>
</body>
</html>

3、编写页面uploadStatus.html

<!--suppress ALL-->
<html xmlns:th="http://www.thymeleaf.org"> <html lang="en">
<head>
<meta charset="UTF-8">
<title>文件上传界面</title>
</head>
<body>
<div th:if="${msg}">
<h2 th:text="${msg}"/>
</div>
<div >
<img src="" th:src="${url}" alt="">
</div>
</body>
</html>

4、编写配置

server.port=8081
spring.servlet.multipart.max-file-size=10MB
spring.servlet.multipart.max-request-size=10MB

5、配置虚拟路径映射

这一步是非常重要的,我们将文件上传到服务器上时,我们需要将我们的请求路径和服务器上的路径进行对应,不然很有可能文件上传成功,但访问失败:

@Configuration
public class MvcConfig implements WebMvcConfigurer { private static final String UPLOADED_FOLDER = System.getProperty("user.dir"); @Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/upload/**")
.addResourceLocations("file:///" + UPLOADED_FOLDER + "/");
}
}

对应关系需要自己去定义,如果访问失败,可以试着打印以下路径,看看是否缺失了路径分隔符。

注意:如果addResourceHandler不要写成处理/**,这样会拦截掉其他的请求

6、测试页面

执行mvn spring-boot:run,启动程序,访问http://localhost:8081/,选择文件,点击上传按钮,我们的项目目录下出现了mongo.jpg,并且页面也成功显示:

四、SpringBoot的Restful风格,返回url

/**
* 文件上传
*
* @author Summerday
*/
@RestController
public class FileUploadRestController { /**
* 文件名长度
*/
private static final int DEFAULT_FILE_NAME_LENGTH = 100; /**
* 允许的文件类型
*/
private static final String[] ALLOWED_EXTENSIONS = {
"jpg", "img", "png", "gif"
}; /**
* 项目路径
*/
private static final String UPLOADED_FOLDER = System.getProperty("user.dir"); @PostMapping("/restUpload")
public Map<String,Object> singleFileUpload(@RequestParam("file") MultipartFile file) throws Exception { if (file.isEmpty()) {
throw new Exception("文件为空!");
}
String filename = upload(file);
String url = "/upload/" + filename;
Map<String,Object> map = new HashMap<>(2);
map.put("msg","上传成功");
map.put("url",url);
return map;
} /**
* 上传方法
*/
private String upload(MultipartFile file) throws Exception {
int len = file.getOriginalFilename().length();
if (len > DEFAULT_FILE_NAME_LENGTH) {
throw new Exception("文件名超出限制!");
}
String extension = getExtension(file);
if(!isValidExtension(extension)){
throw new Exception("文件格式不正确");
}
// 自定义文件名
String filename = getPathName(file);
// 获取file对象
File desc = getFile(filename);
// 写入file
file.transferTo(desc);
return filename;
} /**
* 获取file对象
*/
private File getFile(String filename) throws IOException {
File file = new File(UPLOADED_FOLDER + "/" + filename);
if(!file.getParentFile().exists()){
file.getParentFile().mkdirs();
}
if(!file.exists()){
file.createNewFile();
}
return file;
} /**
* 验证文件类型是否正确
*/
private boolean isValidExtension(String extension) {
for (String allowedExtension : ALLOWED_EXTENSIONS) {
if(extension.equalsIgnoreCase(allowedExtension)){
return true;
}
}
return false;
} /**
* 此处自定义文件名,uuid + extension
*/
private String getPathName(MultipartFile file) {
String extension = getExtension(file);
return UUID.randomUUID().toString() + "." + extension;
} /**
* 获取扩展名
*/
private String getExtension(MultipartFile file) {
String originalFilename = file.getOriginalFilename();
return originalFilename.substring(originalFilename.lastIndexOf('.') + 1);
}
}

五、源码下载

本文内容均为对优秀博客及官方文档总结而得,原文地址均已在文中参考阅读处标注。最后,文中的代码样例已经全部上传至Gitee:https://gitee.com/tqbx/springboot-samples-learn,另有其他SpringBoot的整合哦。

六、参考阅读

SpringBoot实现文件上传功能详解的更多相关文章

  1. iOS 的 Safari 文件上传功能详解

    iOS 6 给 Safari 浏览器带来的另外一个功能是文件上传,终于 Safari 终于支持 input 输入框的文件类型了,并且还支持 HTML媒体捕获(HTML Media Capture). ...

  2. Struts2+Uploadify文件上传使用详解

    Uploadify是JQuery的一个上传插件,实现的效果非常不错,带进度显示.不过官方提供的实例是php版本的,本文将详细介绍Uploadify在java中的使用,您也可以点击下面的链接进行演示或下 ...

  3. Web应用安全之文件上传漏洞详解

    什么是文件上传漏洞 文件上传漏洞是在用户上传了一个可执行的脚本文件,本通过此脚本文件获得了执行服务器端命令的功能,这种攻击方式是最为直接,最为有效的,有时候,几乎没有什么门槛,也就是任何人都可以进行这 ...

  4. php文件上传原理详解(含源码)

    1.文件上传原理 将客户端的文件上传到服务器,再将服务器的临时文件上传到指定目录 2.客户端配置 提交表单 表单的发送方式为post 添加enctype="multipart/form-da ...

  5. jquery组件WebUploader文件上传用法详解

    这篇文章主要为大家详细介绍了jquery组件WebUploader文件上传用法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下 WebUploader是由Baidu WebFE(FEX)团队开发的一 ...

  6. FastDFS的配置、部署与API使用解读(8)FastDFS多种文件上传接口详解(转)

    1.StorageClient与StorageClient1的区别 相信使用happy_fish的FastDFS的童鞋们,一定都熟悉StorageClient了,或者你熟悉的是StorageClien ...

  7. ASP.Net大文件上传组件详解

    首先右键单击网站根目录,在弹出的快捷菜单中,选择"添加引用"菜单项,弹出"添加引用",切换到"浏览"找到组件的Dll文件"Best ...

  8. [js高手之路]深入浅出webpack教程系列2-配置文件webpack.config.js详解(上)

    [js高手之路]深入浅出webpack教程系列索引目录: [js高手之路]深入浅出webpack教程系列1-安装与基本打包用法和命令参数 [js高手之路]深入浅出webpack教程系列2-配置文件we ...

  9. SpringBoot系列(十二)过滤器配置详解

    SpringBoot(十二)过滤器详解 往期精彩推荐 SpringBoot系列(一)idea新建Springboot项目 SpringBoot系列(二)入门知识 springBoot系列(三)配置文件 ...

随机推荐

  1. 主厨(第4部分)- ASP. netNET Core和Angular 2 CRUD SPA

    下载source - 79.7 KB 介绍 在Master Chef(第1部分)和Master Chef(第2部分)中,我介绍了如何使用ASP.Net Core和Angular JS.在Master ...

  2. 【4】进大厂必须掌握的面试题-Java面试-jdbc

    1.什么是JDBC驱动程序? JDBC驱动程序是使Java应用程序与数据库进行交互的软件组件.JDBC驱动程序有4种类型: JDBC-ODBC桥驱动程序 本机API驱动程序(部分为Java驱动程序) ...

  3. 多测师讲解python _练习题002_高级讲师肖sir

    # 1.求出1/1+1/3+1/5--+1/99的和 # 2.用循环语句,计算2-10之间整数的循环相乘的值. # 3.用for循环打印九九乘法表 # 4.求每个字符串中字符出现的个数如:hellow ...

  4. ES异常处理-NoNodeAvailableException

    1.问题描述 ES client客户端能创建,但是在用客户端操作时报:NoNodeAvailableException[None of the configured nodes are availab ...

  5. 《Kafka笔记》2、环境搭建、Topic管理

    目录 一.Kafka环境搭建和Topic管理 1 单机环境搭建 1.1 环境准备 1.1.1 JDK 安装 1.1.2 配置主机名和ip 1.1.3 关闭防火墙和防火墙开机自启动 1.1.4 zook ...

  6. Nexus 安装教程

    Nexus 安装教程 一. CentOS设置 1. 更换阿里源 curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/ ...

  7. sync-player:使用websocket实现异地同步播放视频

    本文作者:星空无限 原文链接:https://liyangzone.com/2020/09/20/前端/sync-player/ GoEasy已获作者授权转载,GoEasy转载时有改动,感谢作者的分享 ...

  8. Unity-根据时间开灯与关灯

    声明:本人只是学生,并且只是自学Unity,如有大神,不喜勿喷,不足之处,请指出! 本项目使用了UniStorm 3.0(天气)插件,时间也是调用它本身的API,实际并不影响,用系统的时间的是也是可以 ...

  9. SLF4J :Failed to load class "org.slf4j.impl.StaticLoggerBinder".

    错误提示 SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder". SLF4J: Defaulting to ...

  10. LeetCode 45跳跃游戏&46全排列

    原创公众号:bigsai,回复进群加入力扣打卡群. 昨日打卡:LeetCode 42字符串相乘&43通配符匹配 跳跃游戏 题目描述: 给定一个非负整数数组,你最初位于数组的第一个位置. 数组中 ...