SpringBoot实现文件上传
SpringBoot实现文件上传
1、创建一个Springboot工程
2、改pom.xml
org.springframework.boot
spring-boot-starter-parent
2.5.6
com.qbb
file-upload
0.0.1-SNAPSHOT
file-upload
Demo project for Spring Boot
1.8
org.springframework.boot
spring-boot-starter-freemarker
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-devtools
runtime
true
org.springframework.boot
spring-boot-configuration-processor
true
org.projectlombok
lombok
true
org.springframework.boot
spring-boot-starter-test
test
org.springframework.boot
spring-boot-maven-plugin
org.projectlombok
lombok
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、业务代码,处理文件上传
在资源目录resources目录下创建一个templates目录
创建一个文件上传的简单页面upload.html
Springboot整合文件上传
-
HelloController添加一下内容
@RequestMapping("/upload")
public String upload(){
return "upload";
} -
测试
-
修改页面代码
-
修改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/
再来测试发现,依然可以