好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

SpringBoot+fileUpload获取文件上传进度

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

写此篇文章之前我查了很多关于spring mvc 框架通过 fileupload 实现进度条的帖子和文章,在此对各位作者表示感谢!

本功能基于commons fileupload 组件实现

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

commonsmultipartresolver 类中相关源码片段:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

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接口实现类:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

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 实体类:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

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 类的自定义文件上传处理类:

 

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

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 类的自定义文件上传处理类。

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

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:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

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:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

<!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>

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

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。

原文链接:https://blog.csdn.net/qq_27607579/article/details/77914958

查看更多关于SpringBoot+fileUpload获取文件上传进度的详细内容...

  阅读:43次