SpringBoot实现文件上传
SpringBoot实现文件上传
1、创建一个Springboot工程
2、改pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.6</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.qbb</groupId>
<artifactId>file-upload</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>file-upload</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</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-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
3、写application.yml/properties文件
server:
port: 9001 # 配置端口号
spring:
freemarker:
suffix: .html # 设置视图模板后缀
cache: false # 不开启缓存
servlet:
multipart:
max-file-size: 10MB # 设置文件大小
enabled: true
4、主启动类
package com.qbb.springboot;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* @author QiuQiu&LL
* @version 1.0
* @createTime 2021-12-15 20:50
* @Description:
*/
@SpringBootApplication
public class FileUploadMain9001 {
public static void main(String[] args) {
SpringApplication.run(FileUploadMain9001.class, args);
}
}
5、编写一个HelloController测试
package com.qbb.springboot.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
/**
* @author QiuQiu&LL
* @version 1.0
* @createTime 2021-12-15 20:52
* @Description:
*/
@Controller
public class HelloController {
@ResponseBody
@RequestMapping("/hello")
public String hello() {
return "Hello FileUpload";
}
}
6、业务代码,处理文件上传
-
1.在资源目录resources目录下创建一个templates目录
-
2.创建一个文件上传的简单页面upload.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>文件上传</title>
</head>
<body>
<h1>Springboot整合文件上传</h1>
</body>
</html>
-
- HelloController添加一下内容
@RequestMapping("/upload")
public String upload(){
return "upload";
}
-
- 测试
-
- 修改页面代码
<!--注意:
enctype="multipart/form-data"
method必须是post请求
input的type是file类型,需要给上name值,controller才能获取
-->
<form action="/upload/file" enctype="multipart/form-data" method="post">
<input name="dir" value="bbs">
<input name="file" type="file">
<input type="submit" value="文件上传">
</form>
-
- 修改controller层代码
/**
* 文件上传具体实现
* @param multipartFile
* @param request
* @return
*/
@PostMapping("/upload/file")
@ResponseBody
public String upload(@RequestParam("file") MultipartFile multipartFile, HttpServletRequest request){
if(multipartFile.isEmpty()){
return "文件有误!!!";
}
long size = multipartFile.getSize();
String originalFilename = multipartFile.getOriginalFilename();
String contentType = multipartFile.getContentType();//imgae/png;image/jpg;image/gif
// if(!contentType.equals("png|jpg|gif")){ //伪代码 ,不正确的代码
// return "文件类型不正确";
// }
// 1: 获取用户指定的文件夹。问这个文件夹为什么要从页面上传递过来呢?
// 原因是:做隔离,不同业务,不同文件放在不同的目录中
String dir = request.getParameter("dir");
return uploadService.uploadImg(multipartFile,dir);
}
-
- 配置文件可以配置文件上传相关信息
servlet:
multipart:
enabled: true
# 是单个文件大小 默认1M 10KB
max-file-size: 2MB
# 是设置总上传的数据大小
max-request-size: 10MB
#当文件达到多少时进行磁盘写入
file-size-threshold: 20MB
# 设置临时目录
location: F://data//tempxxxxxxxxxxxx
-
- 创建uploadService处理文件上传
package com.qbb.springboot.service;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.UUID;
/**
* @author QiuQiu&LL
* @version 1.0
* @createTime 2021-12-15 21:07
* @Description:
*/
@Service
@SuppressWarnings({"all"})
public class UploadService {
@Value("${file.uploadFolder}")
private String uploadFolder;
@Value("${file.staticPath}")
private String staticPath;
/**
* MultipartFile 这个对象是springMvc提供的文件上传的接受的类,
* 它的底层自动会去和HttpServletRequest request中的request.getInputStream()融合
* 从而达到文件上传的效果。也就是告诉你一个道理:
* 文件上传底层原理是:request.getInputStream()
*
* @param multipartFile
* @param dir
* @return
*/
public String uploadImg(MultipartFile multipartFile, String dir) {
try {
String realfilename = multipartFile.getOriginalFilename(); // 上传的文件:aaa.jpg
// 2:截图文件名的后缀
String imgSuffix = realfilename.substring(realfilename.lastIndexOf("."));// 拿到:.jpg
// 3:生成的唯一的文件名:能不能用中文名:不能因为统一用英文命名。
String newFileName = UUID.randomUUID().toString() + imgSuffix;// 将aaa.jpg改写成:SD23423k324-23423ms.jpg
// 4:日期目录
// SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd");
// String datePath = dateFormat.format(new Date());// 日期目录:2021/10/27
// 也可以使用JDK1.8的新时间类LocalDate/LocalDateTime
LocalDate now = LocalDate.now();
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy/MM/dd");
String formatDatePath = formatter.format(now);
// 5: 指定文件上传以后的目录
String servrepath = uploadFolder;// 这不是tomcat服务目录,别人不认识
File targetPath = new File(servrepath + dir, datePath);// 生成一个最终目录:F://tmp/avatar/2021/10/27
if (!targetPath.exists()) targetPath.mkdirs(); // 如果目录不存在:F://tmp/avatar/2021/10/27 递归创建
// 6: 指定文件上传以后的服务器的完整的文件名
File targetFileName = new File(targetPath, newFileName);// 文件上传以后在服务器上最终文件名和目录是:F://tmp/avatar/2021/10/27/SD23423k324-23423ms.jpg
// 7: 文件上传到指定的目录
multipartFile.transferTo(targetFileName);//将用户选择的aaa.jpg上传到F://tmp/avatar/2021/10/27/SD23423k324-23423ms.jpg
// 可访问的路径要返回页面
// http://localhpst:9001/bbs/2021/10/27/5f61dea2-4b77-4068-8d0b-fdf415eac6df.png
String filename = dir + "/" + datePath + "/" + newFileName;
return staticPath + "/" + filename;
} catch (IOException e) {
e.printStackTrace();
return "fail";
}
}
}
- 9.测试
思考:从上面开似乎我们已经完成了文件上传,但是复制该地址会发现,无法通过http请求该服务资源
解决办法:
配置静态资源服务映射
package com.qbb.springboot.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* @author QiuQiu&LL
* @version 1.0
* @createTime 2021-12-16 10:39
* @Description:
*/
@Configuration
public class WebMvcConfiguration implements WebMvcConfigurer {
/**
* springmvc让程序开发者配置文件上传额外的静态资源服务
* @param registry
*/
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/uploadimg/**").addResourceLocations("file:F://temp//");
}
}
核心代码分析
registry.addResourceHandler("访问的路径").addResourceLocations("上传资源的路径");
registry.addResourceHandler("/uploadimg/**").addResourceLocations("file:F://tmp//");
配置完成后测试一下
- 哈哈,功夫不负有心人,效果出现了!!!但是还有问题,我们发现有很多“死代码”不够灵活。如:/uploadimg/** file:F://temp//,都是我们写死的,如何改进呢?
使用配置文件环境隔离解决,使用 - 创建application-dev.yml开发环境配置文件和application-prod.yml生产环境配置文件
- application-dev.yml
# 本机配置
file:
staticPath: http://localhost:9001
staticPatternPath: /upimages/**
uploadFolder: F:/tmp/
- application-prod.yml
# 服务器配置
file:
staticPath: https://www.QIUQIU.com
staticPatternPath: /upimages/**
uploadFolder: /www/upload/
再来测试发现,依然可以
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 张高兴的大模型开发实战:(一)使用 Selenium 进行网页爬虫
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构