依赖添加
需要添加以下两个依赖
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.1</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.6</version>
</dependency>
提交form表单的页面
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="/register/02" method="post" enctype="multipart/form-data">
姓名:<input type="text" name="name"/><br>
年龄:<input type="text" name="age"/><br>
照片:<input type="file" name="file"/><br>
<input type="submit" value="提交"/>
</form>
</body>
</html>
表单中的name和age为普通表单项,file为文件表单项
配置中排除MultipartAutoConfiguration类
因为springboot已经自动配置了MultipartResolver ,导致上传的文件表单项被过滤掉,List fileItems = upload.parseRequest(request)中的list会清0,所有必须在配置中排除MultipartAutoConfiguration类,如下
@SpringBootApplication(exclude = {MultipartAutoConfiguration.class})
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
下面介绍两种编写Controller的方法:
1.控制器(不借助框架,实现文件上传)
@Controller
@RequestMapping("/register")
public class RegisterController {
@RequestMapping("/01")
public void Test01(HttpServletRequest request, HttpServletResponse response) throws IOException, FileUploadException {
//判断请求是否为Multipart请求
if(!ServletFileUpload.isMultipartContent(request)){
throw new RuntimeException("当前请求文件不支持文件上传!");
}
//创建一个FileItem工厂
DiskFileItemFactory factory=new DiskFileItemFactory();
//设置使用临时文件的阀值
factory.setSizeThreshold(1024*1024*1);
//设置一个临时文件,当上传的文件大小超过阀值时,文本创建文件的副本保存在临时文件中
String tempPath="F:\\temp";
File tempFile=new File(tempPath);
factory.setRepository(tempFile);
//创建文件上传核心组件
ServletFileUpload upload=new ServletFileUpload(factory);
//设置每一个item的头部字符编码,其可以解决文件名的中文乱码问题
upload.setHeaderEncoding("UTF-8");
//设置单个上传文件的最大边界值为2M
upload.setFileSizeMax(1024*1024*2);
//设置一次上传所有文件的总大小的最大值为5M(对于上传多个文件时起作用)
upload.setSizeMax(1024*1024*5);
//解析请求
List<FileItem> fileItems = upload.parseRequest(request);
for(FileItem item:fileItems){
if(item.isFormField()){//若item为普通表单项
String fieldName = item.getFieldName();
String fileValue = item.getString("UTF-8");
System.out.println(fieldName+" = "+fileValue);
}else {//若item为文件表单项
String fileName=item.getName();//获取上传文件的原始名称
fileName=System.currentTimeMillis()+fileName;
//获取输入流,其中有上传文件的内容
InputStream inputStream=item.getInputStream();
//获取文件保存在服务器的路径
String path="F:/demo/images";
/*
*设置文件的分级目录管理,将多个文件存放在不同的目录中
*以下方法时按日期进行目录管理,例如D:/file/2021/2/4。
*/
//获取当前系统时间
Calendar nowDate=Calendar.getInstance();
//获取年、月、日
int year=nowDate.get(Calendar.YEAR);
int month=nowDate.get(Calendar.MONTH)+1;
int day=nowDate.get(Calendar.DAY_OF_MONTH);
path=path+"/"+year+"/"+month+"/"+day;
//若该目录不存在,则创建该目录
File dir=new File(path);
if(!dir.exists()){
dir.mkdirs();
}
//创建目标文件,用于保存上传的文件
File file=new File(path,fileName);
//创建文件输出流
OutputStream outputStream=new FileOutputStream(file);
//将输入流的数据写入到输出流中
int len=-1;
byte[] buffer=new byte[1024];
while((len=inputStream.read(buffer))!=-1){
outputStream.write(buffer,0,len);
}
//关闭流
outputStream.close();
inputStream.close();
//删除临时文件
item.delete();
}
}
}
2.控制器(使用MultipartFile,推荐)
注意:使用这种方法时,必须将前面的排除MultipartAutoConfiguration类的配置关掉,重新应用此类。
@RequestMapping("/02")
public String fileUpload( @RequestParam("file") MultipartFile file,String name,Integer age) throws IOException{
//用来检测程序运行时间
long startTime=System.currentTimeMillis();
System.out.println( "fileName:" +file.getOriginalFilename());
String filename =file.getOriginalFilename();
//获取文件保存在服务器的路径
String path="F:/demo/images";
//获取当前系统时间
Calendar nowDate=Calendar.getInstance();
//获取年、月、日
int year=nowDate.get(Calendar.YEAR);
int month=nowDate.get(Calendar.MONTH)+1;
int day=nowDate.get(Calendar.DAY_OF_MONTH);
path=path+"/"+year+"/"+month+"/"+day;
//若该目录不存在,则创建该目录
File dir=new File(path);
if(!dir.exists()){
dir.mkdirs();
}
//文件传输工具类
FtpUtil ftpUtil=new FtpUtil();
ftpUtil.uploadHttpFile(path,filename,file.getInputStream());
long endTime=System.currentTimeMillis();
System.out.println( "采用流上传的方式的运行时间:" +String.valueOf(endTime-startTime)+ "ms" );
//若文件上传成功,则跳转到“文件上传成功”页面
return "/success" ;
}
//上面使用了FtpUtil工具类中的uploadHttpFile方法,将一些样本化的代码进行了封装,如下:
public boolean uploadHttpFile(String filePath, String filename, InputStream input) {
boolean result = false;
FileOutputStream fos = null;
try {
File file = new File(filePath);
if(!file.exists()) {
file.mkdir();
}
fos = new FileOutputStream(filePath + "/" + filename);
byte[] buffer = new byte[1024];
int length;
while ((length = input.read(buffer)) != -1) {
fos.write(buffer, 0, length);
}
input.close();
fos.close();
result = true;
} catch (IOException e) {
logger.error(e.getMessage());
throw new RuntimeException();
} finally {
try {
if (input != null) {
input.close();
}
if (fos != null) {
fos.close();
}
} catch (IOException ignored) {
}
}
return result;
}
可以看出第二种方法编写controller更为简洁