common-fileupload
原创大约 3 分钟
文件上传可以直接使用Commons-FileUpload实现,它提供对文件操作的强大和高性能的封装。
引入依赖。
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.4</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
再编写控制器类。
package com.xiangwang.commons.controller;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
/**
* 上传Controller
*
*/
@RestController
public class FileUploadController {
@Value("${file.path}")
private String filePath;
// 文件上传
@PostMapping("/upload")
public String upload(@RequestParam("file") MultipartFile file, HttpServletRequest request) {
StringBuffer buffer = new StringBuffer();
// 获取原文件名
String filename = file.getOriginalFilename();
try {
File file1 = new File(filePath + filename);
file.transferTo(file1);
} catch (IOException e) {
e.printStackTrace();
}
return "OK";
}
}
如果仅仅只是文件上传,整个功能就已经完成了。但是为了更友好的体验,需要直观的看到上传进度,所以需要继续加入能查看进度的接口。
// 获取上传进度
@GetMapping(value = "/percent")
public Object percent(HttpServletRequest request) {
HttpSession session = request.getSession();
return session.getAttribute("percent");
}
然后在application.properties
文件中加入下面三行。
spring.servlet.multipart.max-file-size=1000MB
spring.servlet.multipart.max-request-size=1000MB
file.path=/home/work/
这里为了观察效果,将上传限制做了放大,然后创建上传进度监听器。
package com.xiangwang.commons.listener;
import org.apache.commons.fileupload.ProgressListener;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpSession;
/**
* 上传进度监听器
*
*/
@Component
public class FileUploadProgressListener implements ProgressListener {
private HttpSession session;
public void setHttpSession(HttpSession session) {
this.session = session;
// 默认进度为0
session.setAttribute("percent", 0);
}
/**
* bytesRead 到目前为止读取文件的比特数
* contentLength 文件总大小
* items 目前正在读取第几个文件
*/
@Override
public void update(long bytesRead, long contentLength, int items) {
int percent = (int) (bytesRead * 100.0 / contentLength);
session.setAttribute("percent", percent);
}
}
再创建上传解析器类。
package com.xiangwang.commons.entity;
import com.xiangwang.commons.listener.FileUploadProgressListener;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUpload;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.springframework.web.multipart.MultipartException;
import org.springframework.web.multipart.commons.CommonsMultipartResolver;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
/**
* 上传解析器
*
*/
public class CustomMultipartResolver extends CommonsMultipartResolver {
@Resource
private FileUploadProgressListener listener;
@Override
protected MultipartParsingResult parseRequest(HttpServletRequest request) throws MultipartException {
String encoding = determineEncoding(request);
FileUpload fileUpload = prepareFileUpload(encoding);
// 文件上传进度监听器设置session用于存储上传进度
listener.setHttpSession(request.getSession());
// 将文件上传进度监听器加入到 fileUpload 中
fileUpload.setProgressListener(listener);
try {
List<FileItem> fileItems = ((ServletFileUpload) fileUpload).parseRequest(request);
return parseFileItems(fileItems, encoding);
} catch (FileUploadException ex) {
throw new MultipartException("Failed to parse multipart servlet request", ex);
}
}
}
创建解析器的配置。
package com.xiangwang.commons.configure;
import com.xiangwang.commons.entity.CustomMultipartResolver;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.multipart.MultipartResolver;
/**
* 配置解析器
*
*/
@Configuration
public class BeanConfigure {
@Bean(name = "multipartResolver")
public MultipartResolver multipartResolver() {
return new CustomMultipartResolver();
}
}
通过Postman测试上传功能。


启动服务后运行测试。
先调用
/percent
接口一次,之后再调用/upload
接口。上传大文件,方便观测效果。
在上传过程中,连续调用
/percent
接口,可以看到上传进度数据不断变化。如果先调用
/upload
,再调用/percent
,是看不到进度数据的。因为需要预先建立会话,才能记录进度,而如果先上传的话,因为上传会占用整个进程,一直到上传结束,才会完成
session
会话的初始化。第一次也可以调用
/upload
,但直到/upload
完成上传之前,调用/percent
都没响应。第一次的
/upload
完成后,第二次调用/upload
,再调用/percent
就可以看到效果了。
感谢支持
更多内容,请移步《超级个体》。