SpringBoot+fileUpload获取文件上传进度
我本人在网上找了很多关于文件上传进度获取的文章,普遍基于springMVC框架通过fileUpload实现,对于springBoot通过fileUpload实现的帖子非常少,由于小弟学艺不精,虽然SpringBoot和SpringMVC相差不大,只是配置方式的差别,还是搞了很久,上传此文章的目的是希望自己作为文本保留,以便日后查看备忘,并且希望通过我的例子可以帮助到其他人而已,如果各位大佬发现小弟对于某些知识有误解,还请不吝赐教,先谢谢各位前辈了!
写此篇文章之前我查了很多关于springMVC框架通过fileUpload实现进度条的帖子和文章,在此对各位作者表示感谢!
本功能基于commonsfileUpload组件实现
1.首先,不能在程序中直接使用fileUpload.parseRequest(request)的方式来获取request请求中的multipartFile文件对象,原因是因为在spring默认的文件上传处理器multipartResolver指向的类CommonsMultipartResolver中就是通过commonsfileUpload组件实现的文件获取,因此,在代码中再次使用该方法,是获取不到文件对象的,因为此时的request对象是不包含文件的,它已经被CommonsMultipartResolver类解析处理并转型。
CommonsMultipartResolver类中相关源码片段:
protectedMultipartParsingResultparseRequest(HttpServletRequestrequest)throwsMultipartException{
Stringencoding=determineEncoding(request);
FileUploadfileUpload=prepareFileUpload(encoding);
try{
ListfileItems=((ServletFileUpload)fileUpload).parseRequest(request);
returnparseFileItems(fileItems,encoding);
}
catch(FileUploadBase.SizeLimitExceededExceptionex){
thrownewMaxUploadSizeExceededException(fileUpload.getSizeMax(),ex);
}
catch(FileUploadBase.FileSizeLimitExceededExceptionex){
thrownewMaxUploadSizeExceededException(fileUpload.getFileSizeMax(),ex);
}
catch(FileUploadExceptionex){
thrownewMultipartException("Failedtoparsemultipartservletrequest",ex);
}
}
2.由于spring中的CommonsMultipartResolver类中并没有加入processListener文件上传进度监听器,所以,直接使用CommonsMultipartResolver类是无法监听文件上传进度的,如果我们需要获取文件上传进度,就需要继承CommonsMultipartResolver类并重写parseRequest方法,在此之前,我们需要创建一个实现了processListener接口的实现类用于监听文件上传进度。
processListener接口实现类:
importjavax.servlet.http.HttpSession;
importorg.apache.commons.fileupload.ProgressListener;
importorg.springframework.stereotype.Component;
@Component
publicclassUploadProgressListenerimplementsProgressListener{
privateHttpSessionsession;
publicvoidsetSession(HttpSessionsession){
this.session=session;
ProgressEntitystatus=newProgressEntity();
session.setAttribute("status",status);
}
/*
*pBytesRead到目前为止读取文件的比特数pContentLength文件总大小pItems目前正在读取第几个文件
*/
@Override
publicvoidupdate(longpBytesRead,longpContentLength,intpItems){
ProgressEntitystatus=(ProgressEntity)session.getAttribute("status");
status.setpBytesRead(pBytesRead);
status.setpContentLength(pContentLength);
status.setpItems(pItems);
}
}
ProgressEntity实体类:
importorg.springframework.stereotype.Component;
@Component
publicclassProgressEntity{
privatelongpBytesRead=0L;//到目前为止读取文件的比特数
privatelongpContentLength=0L;//文件总大小
privateintpItems;//目前正在读取第几个文件
publiclonggetpBytesRead(){
returnpBytesRead;
}
publicvoidsetpBytesRead(longpBytesRead){
this.pBytesRead=pBytesRead;
}
publiclonggetpContentLength(){
returnpContentLength;
}
publicvoidsetpContentLength(longpContentLength){
this.pContentLength=pContentLength;
}
publicintgetpItems(){
returnpItems;
}
publicvoidsetpItems(intpItems){
this.pItems=pItems;
}
@Override
publicStringtoString(){
floattmp=(float)pBytesRead;
floatresult=tmp/pContentLength*100;
return"ProgressEntity[pBytesRead="+pBytesRead+",pContentLength="
+pContentLength+",percentage="+result+"%,pItems="+pItems+"]";
}
}
最后,是继承CommonsMultipartResolver类的自定义文件上传处理类:
importjava.util.List;
importjavax.servlet.http.HttpServletRequest;
importorg.apache.commons.fileupload.FileItem;
importorg.apache.commons.fileupload.FileUpload;
importorg.apache.commons.fileupload.FileUploadBase;
importorg.apache.commons.fileupload.FileUploadException;
importorg.apache.commons.fileupload.servlet.ServletFileUpload;
importorg.springframework.beans.factory.annotation.Autowired;
importorg.springframework.web.multipart.MaxUploadSizeExceededException;
importorg.springframework.web.multipart.MultipartException;
importorg.springframework.web.multipart.commons.CommonsMultipartResolver;
publicclassCustomMultipartResolverextendsCommonsMultipartResolver{
@Autowired
privateUploadProgressListeneruploadProgressListener;
@Override
protectedMultipartParsingResultparseRequest(HttpServletRequestrequest)throwsMultipartException{
Stringencoding=determineEncoding(request);
FileUploadfileUpload=prepareFileUpload(encoding);
uploadProgressListener.setSession(request.getSession());//问文件上传进度监听器设置session用于存储上传进度
fileUpload.setProgressListener(uploadProgressListener);//将文件上传进度监听器加入到fileUpload中
try{
ListfileItems=((ServletFileUpload)fileUpload).parseRequest(request);
returnparseFileItems(fileItems,encoding);
}
catch(FileUploadBase.SizeLimitExceededExceptionex){
thrownewMaxUploadSizeExceededException(fileUpload.getSizeMax(),ex);
}
catch(FileUploadBase.FileSizeLimitExceededExceptionex){
thrownewMaxUploadSizeExceededException(fileUpload.getFileSizeMax(),ex);
}
catch(FileUploadExceptionex){
thrownewMultipartException("Failedtoparsemultipartservletrequest",ex);
}
}
}
3.此时,所有需要的类已经准备好,接下来我们需要将spring默认的文件上传处理类取消自动配置,并将multipartResolver指向我们刚刚创建好的继承CommonsMultipartResolver类的自定义文件上传处理类。
importorg.springframework.boot.SpringApplication;
importorg.springframework.boot.autoconfigure.EnableAutoConfiguration;
importorg.springframework.boot.autoconfigure.web.MultipartAutoConfiguration;
importorg.springframework.boot.web.servlet.ServletComponentScan;
importorg.springframework.context.annotation.Bean;
importorg.springframework.context.annotation.ComponentScan;
importorg.springframework.context.annotation.Configuration;
importorg.springframework.web.multipart.MultipartResolver;
importcom.example.listener.CustomMultipartResolver;
/*
*将spring默认的文件上传处理类取消自动配置,这一步很重要,没有这一步,当multipartResolver重新指向了我们定义好
*的新的文件上传处理类后,前台传回的file文件在后台获取会是空,加上这句话就好了,推测不加这句话,spring依然
*会先走默认的文件处理流程并修改request对象,再执行我们定义的文件处理类。(这只是个人推测)
*exclude表示自动配置时不包括Multipart配置
*/
@EnableAutoConfiguration(exclude={MultipartAutoConfiguration.class})
@Configuration
@ComponentScan(basePackages={"com.example"})
@ServletComponentScan(basePackages={"com.example"})
publicclassUploadProgressApplication{
/*
*将multipartResolver指向我们刚刚创建好的继承CommonsMultipartResolver类的自定义文件上传处理类
*/
@Bean(name="multipartResolver")
publicMultipartResolvermultipartResolver(){
CustomMultipartResolvercustomMultipartResolver=newCustomMultipartResolver();
returncustomMultipartResolver;
}
publicstaticvoidmain(String[]args){
SpringApplication.run(UploadProgressApplication.class,args);
}
}
至此,准备工作完成,我们再创建一个测试用的controller和html页面用于文件上传。
controller:
importorg.springframework.stereotype.Controller;
importorg.springframework.web.bind.annotation.RequestMapping;
importorg.springframework.web.bind.annotation.RequestMethod;
importorg.springframework.web.bind.annotation.ResponseBody;
importorg.springframework.web.multipart.MultipartFile;
importorg.springframework.web.servlet.ModelAndView;
@Controller
@RequestMapping("/uploadProgress")
publicclassUploadController{
@RequestMapping(value="/showUpload",method=RequestMethod.GET)
publicModelAndViewshowUpload(){
returnnewModelAndView("/UploadProgressDemo");
}
@RequestMapping("/upload")
@ResponseBody
publicvoiduploadFile(MultipartFilefile){
System.out.println(file.getOriginalFilename());
}
}
HTML:
测试 这里写代码片 这是文件上传页面
经本人测试,确实可以获取文件上传进度,前台页面修改进度条进度可以采用前台页面轮询的方式访问后台,在相应action中通过存储在session中的对象status来获取最新的上传进度并返回展示即可。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。