温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

如何在SpringBoot中使用fileUpload获取文件的上传进度

发布时间:2021-01-28 10:51:08 来源:亿速云 阅读:484 作者:Leah 栏目:编程语言

这篇文章将为大家详细讲解有关如何在SpringBoot中使用fileUpload获取文件的上传进度,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。

本功能基于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<FileItem> 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
public 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; 
  } 
  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<FileItem> 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.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:

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8"></meta>
  <title>测试</title>这里写代码片
</head>
<body>
  这是文件上传页面
  <form action="/uploadProgress/upload" method="POST" enctype="multipart/form-data">
    <input type="file" name="file"/>
    <br/>
    <input type="submit" value="提交"/>
  </form>
</body>
</html>

关于如何在SpringBoot中使用fileUpload获取文件的上传进度就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI