SpringBoot+fileUpload获取文件上传进度

网友投稿 671 2023-01-23


SpringBoot+fileUpload获取文件上传进度

我本人在网上找了很多关于文件上传进度获取的文章,普遍基于spring MVC 框架通过 fileUpload 实现,对于spring Boot 通过 fileUpload 实现的帖子非常少,由于小弟学艺不精,虽然 Spring Boot 和 Spring MVC 相差不大,只是配置方式的差别,还是搞了很久,上传此文章的目的是希望自己作为文本保留,以便日后查看备忘,并且希望通过我的例子可以帮助到其他人而已,如果各位大佬发现小弟对于某些知识有误解,还请不吝赐教,先谢谢各位前辈了!

本功能基于commons fileUpload 组件实现

1.首先,不能在程序中直接使用 fileUpload.parseRequest(request)的方式来获取 request 请求中的 multipartFile 文件对象,原因是因为在 spring 默认的文件上传处理器 multipartResolver 指向的类CommonsMultipartResolver 中就是通过 commons fileUpload 组件实现的文件获取,因此,在代码中再次使用该方法,是获取不到文件对象的,因为此时的 request 对象是不包含文件的,它已经被CommonsMultipartResolver 类解析处理并转型。

CommonsMultipartResolver 类中相关源码片段:

protected MultipartParsingResult parseRequest(HttpServletRequest request) throws MultipartException {

String encoding = determineEncoding(request);

FileUpload fileUpload = prepareFileUpload(encoding);

try {

List fileItems = ((ServletFileUpload) fileUpload).parseRequest(request);

return parseFileItems(fileItems, encoding);

}

catch (FileUploadBase.SizeLimitExceededException ex) {

throw new MaxUploadSizeExceededException(fileUpload.getSizeMax(), ex);

}

catch (FileUploadBase.FileSizeLimitExceededException ex) {

throw new MaxUploadSizeExceededException(fileUpload.getFileSizeMax(), ex);

}

catch (FileUploadException ex) {

throw new MultipartException("Failed to parse multipart servlet request", ex);

}

}

2.由于spring 中的 CommonsMultipartResolver 类中并没有加入 processListener 文件上传进度监听器,所以,直接使用 CommonsMultipartResolver 类是无法监听文件上传进度的,如果我们需要获取文件上传进度,就需要继承 CommonsMultipartResolver 类并重写 parseRequest 方法,在此之前,我们需要创建一个实现了 processListener 接口的实现类用于监听文件上传进度。

processListener接口实现类:

import javax.servlet.http.HttpSession;

import org.apache.commons.fileupload.ProgressListener;

import org.springframework.stereotype.Component;

@Component

public class UploadProgressListener implements ProgressListener{

private HttpSession session;

public void setSession(HttpSession session){

this.session=session;

ProgressEntity status = new ProgressEntity();

session.setAttribute("status", status);

}

/*

* pBytesRead 到目前为止读取文件的比特数 pContentLength 文件总大小 pItems 目前正在读取第几个文件

*/

@Override

public void update(long pBytesRead, long pContentLength, int pItems) {

ProgressEntity status = (ProgressEntity) session.getAttribute("status");

status.setpBytesRead(pBytesRead);

status.setpContentLength(pContentLength);

status.setpItems(pItems);

}

}

ProgressEntity 实体类:

import org.springframework.stereotype.Component;

@Component

pubcqOxyAUlic class ProgressEntity {

private long pBytesRead = 0L; //到目前为止读取文件的比特数

private long pContentLength = 0L; //文件总大小

private int pItems; //目前正在读取第几个文件

public long getpBytesRead() {

return pBytesRead;

}

public void setpBytesRead(long pBytesRead) {

this.pBytesRead = pBytesRead;

}

public long getpContentLength() {

return pContentLength;

}

public void setpContentLength(long pContentLength) {

this.pContentLength = pContentLength;

http:// }

public int getpItems() {

return pItems;

}

public void setpItems(int pItems) {

this.pItems = pItems;

}

@Override

public String toString() {

float tmp = (float)pBytesRead;

float result = tmp/pContentLength*100;

return "ProgressEntity [pBytesRead=" + pBytesRead + ", pContentLength="

+ pContentLength + ", percentage=" + result + "% , pItems=" + pItems + "]";

}

}

最后,是继承 CommonsMultipartResolver 类的自定义文件上传处理类:

import java.util.List;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.fileupload.FileItem;

import org.apache.commons.fileupload.FileUpload;

import org.apache.commons.fileupload.FileUploadBase;

import org.apache.commons.fileupload.FileUploadException;

import org.apache.commons.fileupload.servlet.ServletFileUpload;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.web.multipart.MaxUploadSizeExceededException;

import org.springframework.web.multipart.MultipartException;

import org.springframework.web.multipart.commons.CommonsMultipartResolver;

public class CustomMultipartResolver extends CommonsMultipartResolver{

@Autowired

private UploadProgressListener uploadProgressListener;

@Override

protected MultipartParsingResult parseRequest(HttpServletRequest request) throws MultipartException {

String encoding = determineEncoding(request);

FileUpload fileUpload = prepareFileUpload(encoding);

uploadProgressListener.setSession(request.getSession());//问文件上传进度监听器设置session用于存储上传进度

fileUpload.setProgressListener(uploadProgressListener);//将文件上传进度监听器加入到 fileUpload 中

try {

List fileItems = ((ServletFileUpload) fileUpload).parseRequest(request);

return parseFileItems(fileItems, encoding);

}

catch (FileUploadBase.SizeLimitExceededException ex) {

throw new MaxUploadSizeExceededException(fileUpload.getSizeMax(), ex);

}

catch (FileUploadBase.FileSizeLimitExceededException ex) {

throw new MaxUploadSizeExceededException(fileUpload.getFileSizeMax(), ex);

}

catch (FileUploadException ex) {

throw new MultipartException("Failed to parse multipart servlet request", ex);

}

}

}

3.此时,所有需要的类已经准备好,接下来我们需要将 spring 默认的文件上传处理类取消自动配置,并将 multipartResolver 指向我们刚刚创建好的继承 CommonsMultipartResolver 类的自定义文件上传处理类。

import org.springframework.boot.SpringApplication;

import org.springframework.boot.autoconfigure.EnableAutoConfiguration;

import org.springframework.boot.autoconfigure.web.MultipartAutoConfiguration;

import org.springframework.boot.web.servlet.ServletComponentScan;

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.ComponentScan;

import org.springframework.context.annotation.Configuration;

import org.springframework.web.multipart.MultipartResolver;

import com.example.listener.CustomMultipartResolver;

/*

* 将 spring 默认的文件上传处理类取消自动配置,这一步很重要,没有这一步,当multipartResolver重新指向了我们定义好

* 的新的文件上传处理类后,前台传回的 file 文件在后台获取会是空,加上这句话就好了,推测不加这句话,spring 依然

* 会先走默认的文件处理流程并修改request对象,再执行我们定义的文件处理类。(这只是个人推测)

* exclude表示自动配置时不包括Multipart配置

*/

@EnableAutoConfiguration(exclude = {MultipartAutoConfiguration.class})

@Configuration

@ComponentScan(basePackages = {"com.example"})

@ServletComponentScan(basePackages = {"com.example"})

public class UploadProgressApplication {

/*

* 将 multipartResolver 指向我们刚刚创建好的继承 CommonsMultipartResolver 类的自定义文件上传处理类

*/

@Bean(name = "multipartResolver")

public MultipartResolver multipartResolver() {

CustomMultipartResolver customMultipartResolver = new CustomMultipartResolver();

return customMultipartResolver;

}

public static void main(String[] args) {

SpringApplication.run(UploadProgressApplication.class, args);

}

}

至此,准备工作完成,我们再创建一个测试用的 controller 和 html 页面用于文件上传。

controller:

import org.springframework.stereotype.Controller;

import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.bind.annotation.RequestMethod;

import org.springframework.web.bind.annotation.ResponseBody;

import org.springframework.web.multipart.MultipartFile;

import org.http://springframework.web.servlet.ModelAndView;

@Controller

@RequestMapping("/uploadProgress")

public class UploadController {

@RequestMapping(value = "/showUpload", method = RequestMethod.GET)

public ModelAndView showUpload() {

return new ModelAndView("/UploadProgressDemo");

}

@RequestMapping("/upload")

@ResponseBody

public void uploadFile(MultipartFile file) {

System.out.println(file.getOriginalFilename());

}

}

HTML:

这是文件上传页面


经本人测试,确实可以获取文件上传进度,前台页面修改进度条进度可以采用前台页面轮询的方式访问后台,在相应action中通过存储在session中的对象 status 来获取最新的上传进度并返回展示即可。


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:Java泛型定义与用法实例详解
下一篇:Java集合定义与用法实例总结【Set、List与Map】
相关文章

 发表评论

暂时没有评论,来抢沙发吧~