当前位置:网站首页>16. 文件上传
16. 文件上传
2022-08-10 23:35:00 【要学就学灰太狼】
文章目录
16.1 应用实例
16.1.1 需求说明
- 演示 Spring-Boot 通过表单注册用户,并支持上传图片
- 回顾 SpringMVC 文件上传 ==> 文章链接
16.1.2 代码实现
- 创建 templates/upload.html,要求头像只能选择一个,而宠物可以上传多个图片
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>upload</title>
</head>
<body bgcolor="#CED3FE">
<img src="images/1.GIF"/>
<hr/>
<div style="text-align: center">
<h1>注册用户~</h1>
<form action="#" method="post" th:action="@{/upload}" enctype="multipart/form-data">
用户名:<input type="text" style="width:150px" name="name"/><br/><br/>
电 邮:<input type="text" style="width:150px" name="email"/><br/><br/>
年 龄:<input type="text" style="width:150px" name="age"/><br/><br/>
职 位:<input type="text" style="width:150px" name="job"/><br/><br/>
头 像:<input type="file" style="width:150px" name="header"><br/><br/>
宠 物:<input type="file" style="width:150px" name="photos" multiple><br/><br/>
<input type="submit" value="注册"/>
<input type="reset" value="重新填写"/>
</form>
</div>
<hr/>
<!--<img src="images/logo.png"/>-->
</body>
</html>
- 创建 D:\xjs_springboot\springboot-usersys\src\main\java\com\xjs\springboot\controller\UploadController.java
package com.xjs.springboot.controller;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Controller;
import org.springframework.util.ResourceUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.io.IOException;
/** * @Author: 谢家升 * @Version: 1.0 */
@Controller
@Slf4j
public class UploadController {
//处理转发到用户注册-完成文件上传页面
@GetMapping("/upload.html")
public String uploadPage() {
return "upload"; //thymeleaf 视图解析,转发到 templates/upload.html
}
//处理用户的注册请求-包括处理文件上传
@PostMapping("/upload")
@ResponseBody
public String upload(@RequestParam("name") String name,
@RequestParam("email") String email,
@RequestParam("age") Integer age,
@RequestParam("job") String job,
@RequestParam("header") MultipartFile header,
@RequestParam("photos") MultipartFile[] photos) throws IOException {
//输出获取到的信息
log.info("上传的信息 name={} email={} age={} job={} header={} photos={}",
name, email, age, job, header.getSize(), photos.length);
//我们将文件保存到指定的目录,比如 D:\\temp_upload
//1. 先将文件保存到指定的目录 比如 D:\\temp_upload
if (!header.isEmpty()) {
//处理头像
//获取上传的文件的原文件名
String originalFilename = header.getOriginalFilename();
header.transferTo(new File("D:\\temp_upload\\" + originalFilename));
}
//处理宠物图片
if (photos.length > 0) {
for (MultipartFile photo : photos) {
//遍历
if (!photo.isEmpty()) {
String originalFilename = photo.getOriginalFilename();
photo.transferTo(new File("D:\\temp_upload\\" + originalFilename));
}
}
}
//==============================================
//2. 后面再演示把文件保存到动态创建的目录中
// 比如:类路径下的
//(1) 先得到类路径(运行的时候)
String path = ResourceUtils.getURL("classpath:").getPath();
//log.info("path={}", path);
//(2)动态创建指定的目录
File file = new File(path + "static/images/upload/");
if (!file.exists()) {
//如果目录不存在 就创建
file.mkdirs();
}
//处理头像
if (!header.isEmpty()) {
String originalFilename = header.getOriginalFilename();
//这里需要指定保存文件的绝对路径,即:
//log.info("保存文件的绝对路径={}", file.getAbsolutePath());
// 输出即可看出路径拼接的时候是否需要加 "/"
//保存到动态创建的目录
header.transferTo(new File(file.getAbsoluteFile() + "/" + originalFilename));
}
//处理宠物图片
if (photos.length > 0) {
for (MultipartFile photo : photos) {
String originalFilename = photo.getOriginalFilename();
//保存到动态创建的目录
photo.transferTo(new File(file.getAbsoluteFile() + "/" + originalFilename));
}
}
return "注册用户成功/文件上传成功";
}
}
- 修改 WebConfig 配置,放行/upload.html 和 /upload 请求
package com.xjs.springboot.config;
import com.xjs.springboot.interceptor.LoginInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/** * @Author: 谢家升 * @Version: 1.0 */
@Configuration
public class WebConfig /*implements WebMvcConfigurer*/ {
//@Override
//public void addInterceptors(InterceptorRegistry registry) {
//
// //注册自定义拦截器LoginInterceptor
// registry.addInterceptor(new LoginInterceptor())
// .addPathPatterns("/**") //这里拦截所有的请求
// .excludePathPatterns("/","/login","/images/**"); //指定要放行的,根据业务需要来添加放行的请求路径
//
//}
@Bean
public WebMvcConfigurer webMvcConfigurer() {
return new WebMvcConfigurer() {
@Override
public void addInterceptors(InterceptorRegistry registry) {
//注册拦截器
registry.addInterceptor(new LoginInterceptor())
.addPathPatterns("/**")
.excludePathPatterns("/", "/login", "/images/**", "/upload.html", "/upload");
}
};
}
}
- 根据项目需求修改文件上传的参数,否则文件上传会抛出异常
创建 resources\application.yml 修改文件上传配置参数
①
max-file-size
单个文件大小
②max-request-size
一次请求最大上传大小 (多个文件)
spring:
servlet:
multipart:
max-file-size: 10MB # 表示单个文件上传最大 10MB
max-request-size: 50MB # 表示一次请求上传多文件最多上传 10MB
16.1.3 完成注册用户/上传图片 -测试
16.1.3.1 启动项目
16.1.3.2 浏览器:http://localhost:8080/upload.html
16.1.3.3 页面效果
16.1.4 课后作业-扩展要求
- 解决文件覆盖问题,如果文件名相同,会出现覆盖问题,如何解决?
- 解决文件分目录存放问题,如果将文件都上传到一个目录下,当上传文件很多时,会造成访问文件速度变慢,因此 可以将文件上传到不同目录 比如 一天上传的文件,统一放到一个文件夹 年/月/日,比如 2022/11/11 目录
- 参考前面学的 java web ==> 文章链接
16.1.5 课后作业解答
- 生成一个唯一标识的文件名即可
String fileName = UUID.randomUUID().toString()+"_"+System.currentTimeMillis()+"_" +originalFilename;
- 修改 UploadController.java
package com.xjs.springboot.controller;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Controller;
import org.springframework.util.ResourceUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.io.IOException;
import java.util.UUID;
/** * @Author: 谢家升 * @Version: 1.0 */
@Controller
@Slf4j
public class UploadController {
//处理转发到用户注册-完成文件上传页面
@GetMapping("/upload.html")
public String uploadPage() {
return "upload"; //thymeleaf 视图解析,转发到 templates/upload.html
}
//处理用户的注册请求-包括处理文件上传
@PostMapping("/upload")
@ResponseBody
public String upload(@RequestParam("name") String name,
@RequestParam("email") String email,
@RequestParam("age") Integer age,
@RequestParam("job") String job,
@RequestParam("header") MultipartFile header,
@RequestParam("photos") MultipartFile[] photos) throws IOException {
//输出获取到的信息
log.info("上传的信息 name={} email={} age={} job={} header={} photos={}",
name, email, age, job, header.getSize(), photos.length);
//我们将文件保存到指定的目录,比如 D:\\temp_upload
//1. 先将文件保存到指定的目录 比如 D:\\temp_upload
//if (!header.isEmpty()) { //处理头像
// //获取上传的文件的原文件名
// String originalFilename = header.getOriginalFilename();
// header.transferTo(new File("D:\\temp_upload\\" + originalFilename));
//}
//处理宠物图片
//if (photos.length > 0) {
// for (MultipartFile photo : photos) { //遍历
// if (!photo.isEmpty()) {
// String originalFilename = photo.getOriginalFilename();
// photo.transferTo(new File("D:\\temp_upload\\" + originalFilename));
// }
// }
//}
//==============================================
//2. 后面再演示把文件保存到动态创建的目录中
// 比如:类路径下的
//(1) 先得到类路径(运行的时候)
String path = ResourceUtils.getURL("classpath:").getPath();
//log.info("path={}", path);
//(2)动态创建指定的目录
File file = new File(path + "static/images/upload/");
if (!file.exists()) {
//如果目录不存在 就创建
file.mkdirs();
}
//处理头像
if (!header.isEmpty()) {
String originalFilename = header.getOriginalFilename();
String fileName = UUID.randomUUID().toString()+"_"+System.currentTimeMillis()+"_" +originalFilename;
//这里需要指定保存文件的绝对路径,即:
//log.info("保存文件的绝对路径={}", file.getAbsolutePath());
// 输出即可看出路径拼接的时候是否需要加 "/"
//保存到动态创建的目录
//header.transferTo(new File(file.getAbsoluteFile() + "/" + originalFilename));
header.transferTo(new File(file.getAbsoluteFile() + "/" + fileName));
}
//处理宠物图片
if (photos.length > 0) {
for (MultipartFile photo : photos) {
String originalFilename = photo.getOriginalFilename();
String fileName = UUID.randomUUID().toString()+"_"+System.currentTimeMillis()+"_" +originalFilename;
//保存到动态创建的目录
//photo.transferTo(new File(file.getAbsoluteFile() + "/" + originalFilename));
photo.transferTo(new File(file.getAbsoluteFile() + "/" + fileName));
}
}
return "注册用户成功/文件上传成功";
}
}
- 编写一个工具类,根据当前日期生成对应目录即可
- 编写工具类 WebUtils.java
package com.xjs.springboot.utils;
import java.text.SimpleDateFormat;
import java.util.Date;
/** * @Author: 谢家升 * @Version: 1.0 */
public class WebUtils {
//定义一个文件上传的路径
public static String UPLOAD_FILE_DIRECTORY = "static/images/upload/";
//编写方法, 根据当前日期生成目录 年/月/日
public static String getUploadFileDirectory() {
return UPLOAD_FILE_DIRECTORY + new SimpleDateFormat("yyyy/MM/dd").format(new Date());
}
//测试
public static void main(String[] args) {
System.out.println(WebUtils.getUploadFileDirectory());
}
}
- 修改 UploadController.java
package com.xjs.springboot.controller;
import com.xjs.springboot.utils.WebUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Controller;
import org.springframework.util.ResourceUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.io.IOException;
import java.util.UUID;
/** * @Author: 谢家升 * @Version: 1.0 */
@Controller
@Slf4j
public class UploadController {
//处理转发到用户注册-完成文件上传页面
@GetMapping("/upload.html")
public String uploadPage() {
return "upload"; //thymeleaf 视图解析,转发到 templates/upload.html
}
//处理用户的注册请求-包括处理文件上传
@PostMapping("/upload")
@ResponseBody
public String upload(@RequestParam("name") String name,
@RequestParam("email") String email,
@RequestParam("age") Integer age,
@RequestParam("job") String job,
@RequestParam("header") MultipartFile header,
@RequestParam("photos") MultipartFile[] photos) throws IOException {
//输出获取到的信息
log.info("上传的信息 name={} email={} age={} job={} header={} photos={}",
name, email, age, job, header.getSize(), photos.length);
//我们将文件保存到指定的目录,比如 D:\\temp_upload
//1. 先将文件保存到指定的目录 比如 D:\\temp_upload
//if (!header.isEmpty()) { //处理头像
// //获取上传的文件的原文件名
// String originalFilename = header.getOriginalFilename();
// header.transferTo(new File("D:\\temp_upload\\" + originalFilename));
//}
//处理宠物图片
//if (photos.length > 0) {
// for (MultipartFile photo : photos) { //遍历
// if (!photo.isEmpty()) {
// String originalFilename = photo.getOriginalFilename();
// photo.transferTo(new File("D:\\temp_upload\\" + originalFilename));
// }
// }
//}
//==============================================
//2. 后面再演示把文件保存到动态创建的目录中
// 比如:类路径下的
//(1) 先得到类路径(运行的时候)
String path = ResourceUtils.getURL("classpath:").getPath();
//log.info("path={}", path);
//(2)动态创建指定的目录
File file = new File(path + WebUtils.getUploadFileDirectory());
if (!file.exists()) {
//如果目录不存在 就创建
file.mkdirs();
}
//处理头像
if (!header.isEmpty()) {
String originalFilename = header.getOriginalFilename();
String fileName = UUID.randomUUID().toString()+"_"+System.currentTimeMillis()+"_" +originalFilename;
//这里需要指定保存文件的绝对路径,即:
//log.info("保存文件的绝对路径={}", file.getAbsolutePath());
// 输出即可看出路径拼接的时候是否需要加 "/"
//保存到动态创建的目录
//header.transferTo(new File(file.getAbsoluteFile() + "/" + originalFilename));
header.transferTo(new File(file.getAbsoluteFile() + "/" + fileName));
}
//处理宠物图片
if (photos.length > 0) {
for (MultipartFile photo : photos) {
String originalFilename = photo.getOriginalFilename();
String fileName = UUID.randomUUID().toString()+"_"+System.currentTimeMillis()+"_" +originalFilename;
//保存到动态创建的目录
//photo.transferTo(new File(file.getAbsoluteFile() + "/" + originalFilename));
photo.transferTo(new File(file.getAbsoluteFile() + "/" + fileName));
}
}
return "注册用户成功/文件上传成功";
}
}
边栏推荐
猜你喜欢
随机推荐
好用的翻译插件-一键自动翻译插件软件
6.0深入理解MySQL事务隔离级别与锁机制
Kubernetes 计算CPU 使用率
闭包详解,柯里化的含义及操作方法
MySQL数据库基础操作
编程语言为什么有变量类型这个概念?
CSAPP lab
特殊类与类型转换
Kotlin 由浅入深,带你搞懂协程异常处理的那点事
服务器小常识
有趣并发性能分享:线程池为什么设计成这样?
Mathematical modeling preparation knowledge
互联网中不可缺失的网络优化:“App与Server的交互依赖于网络”
App基础优化三部曲:启动原理&黑白屏优化&启动时间优化
Deep Learning Transformer Architecture Analysis
vr工业操作培训模拟系统可以应用到哪些场景中
HPb59-1铅黄铜
Redis - Use lua script to control the number of wrong passwords and lock the account
u盘数据不小心删除怎么恢复,u盘数据删除如何恢复
如何快速把握行业机会,更高效地推陈出新,是一个重要的命题