有你在真好 的个人博客
实现文件上传的几种方式
阅读:2333 添加日期:2021/3/27 23:27:53 原文链接:https://www.toutiao.com/item/6341955287796154882/

实现文件上传的几种方式文件的上传和下载功能是一个系统的基本功能,任何系统的需求基本上都会设计上传和下载,下载相对简单,今天我们单独就文件上传的几种方式。下面是案例的结构图:

实现文件上传的几种方式

1、 struts2提供的文件上传机制

首先,我们来看一下struts2为我们提供了什么样的上传机制。那在讲解之前我们需要简单的搭建一个struts2的框架:

Jar包:

实现文件上传的几种方式

XML文件:

实现文件上传的几种方式



实现文件上传的几种方式

从JAR包我们就可以发现,struts2提供的文件上传机制其实是建立在apache提供的commons-fileupload.jar基础上的。从WEB.xml文件中我们发现我使用的过滤器不是struts2默认的过滤器,而是我自己自定义的过滤器ExtendStrutsFilter,他继承了
StrutsPrepareAndExecuteFilter,至于这个过滤器我们一会看情况来介绍;一般情况下我们配置的过滤器是
StrutsPrepareAndExecuteFilter。

搭建成功后,启动tomcat如果不报异常基本就没问题了。下面我们通过一个简单的文件上传案例来看以下struts2如何完成文件上传的,首先我们需要创建一个页面,写一个表单,表单的组件是File类型的字段,还有一个提交按钮:

实现文件上传的几种方式

特别要注意的一点是enctype这个类型一定要写成multipart/form-data,这表示提交方式以二进制形式请求的。这样后台才能通过二进制方式去解析。下面我们创建一个action类,有File类型的对象和文件名称,和相关方法,一个上传方法负责把文件放置在指定目录。具体代码如下:

实现文件上传的几种方式

如果上传成功就执行success页面,反之就是error页面:

实现文件上传的几种方式

这样的话代码基本就搞定了,当然我们可以在struts2的配置文件里加上一些拦截器,配置文件上传的一些类型限制和大小限制,这里就不写了。下面来进行以下文件上传的测试,首先清空文件服务器里的文件,然后执行上传:

实现文件上传的几种方式

实现文件上传的几种方式

实现文件上传的几种方式

结果显示上传成功。

2、使用COS组件完成上传

我们的项目中如果不使用struts2框架,自然就不能使用它提供的上传机制,那此时我们需要使用其他技术,我们可以使用原生的Commons-fileupload,但我们自己来写考虑的情况不完善,所以很多时候其实我们是使用一些成熟的上传组件,例如COS就是一款不错的选择:

使用COS组件完成上传是比较简单的,只要通过一个构造方法,提供给他相关的参数,例如文件名称,保存路径,编码等,它就能自动帮助我们完成文件上传,但是为了完善我们的代码,我们需要对其再进行一次封装,例如这些参数,我们可以使用一个名曰UploadSetting的对象去封装,对于上传成功的文件,我们可以通过UploadFile的对象去封装;下面我们来看一下具体的代码,首先导入jar包:

实现文件上传的几种方式

创建servlet,并在web.xml中注册:

实现文件上传的几种方式

下面看以下页面:

实现文件上传的几种方式

简单做个解释,首先是一个表单,通过事件方式完成属性对象构建,然后提交form表单到cosFileUploadServlet。这里我们插一句,我在做测试时并没有发现有什么问题,也许有的时候struts2和COS组件不能兼容。所以如果想在struts2里使用cos,必须在过滤器上动动手脚。就如同上述说过的ExtendStrutsFilter:

实现文件上传的几种方式

这里大家参考一下这种思路。最后我们看一下cos组件上传servlet的代码,首先我们重载了父类的service方法,因为熟悉servlet生命周期的同学一定清楚,请求servlet先进入的是init方法,然后就是service方法,通过service然后去执行doPost或者doGet,我们在service里去构造文件的相关参数,然后传递给doPost方法:

实现文件上传的几种方式

我们获取页面传递给我们的关于保存路径,文件大小限制,允许的文件类型以及编码格式等,通过构造函数构造了uploadSetting对象,传递给doPost执行上传工作,doPost方法的代码如下,代码比较长,分两个截图:

实现文件上传的几种方式

在这里我们一定很想知道到底COS组件是如何完成文件上传的,它的内在机制和原理是什么,这里我们就需要研究一下它的源代码了,但是肯定我们研究不透彻,但是仔细找找我们是可以找到核心代码的例如:

实现文件上传的几种方式

我们发现其实它的底层就是通过IO流的方式来for循环读写文件本身的。具体源文件我们就不过多解释了,然后来看第二个截图:

实现文件上传的几种方式

这个图片的代码是for循环上传元素,其中part对象并不是一定就是文件,也可能是字符串字段等,这里我们做了判断,如果这个part是文件类型的话,我们就截取它的名字来构造uploadFile对象。当然这里我们没有使用到它。因为只是一个模拟案例而已。在这段代码中我们需要知道的一个重点时,我们如何对文件重命名,我们其实可以有两种机制:第一是使用cos提供的重命名方式,第二是等文件上传成功后我们自己通过IO的rename方法重命名,第二种谁都会,这里我们推荐使用第一种方式,那COS是如何完成文件重命名的呢,这里我们需要讲一下:

在第一张图里我们构建了一个UploadFileRenamePolicy对象:这个类是用于重命名的类,我们发现这个类是我们自定义的一个类,而它实现了FileRenamePolicy接口。这个接口的代码是什么呢:

实现文件上传的几种方式

我们发现这个接口就一个抽象方法,就是关于重命名的方式,此时我们需要实现该方法,并自己定义重命名的实际代码。我们的代码是这么写的:

实现文件上传的几种方式

那这个类的对象我们构造好了以后,COS又是在什么时机完成的文件重命名呢,在第二张图里,我们调用了这么一个方法:

实现文件上传的几种方式

我们通过源码可以看到:

实现文件上传的几种方式

源代码中,程序判断了如果这个对象不为null的话就去调用这个对象的rename方法,然后将该文件重命名为新的文件名称,如此就完成了cos组件的上传和重命名工作。通过以上讲述我们就能清晰的了解了COS的上传流程和工作原理。

3、 使用原生的Commons-fileupload.jar完成文件上传

前面我们讲到了使用struts和cos完成的文件的上传,也讲了其实现原理,其实都是借鉴和参考了Commons-fileupload.jar的内在机制。当系统中不允许使用cos组件,也不使用struts时,我们可以考虑从其底层出发。现在我们就学习一下如何使用Commons-fileupload.jar的相关代码完成文件上传。首先导入jar包,其实jar包已经导入了,因为在struts2的jar包里已经包含了他们:

实现文件上传的几种方式

对于Servlet,我们先不看代码,我们来讲一下具体的原理:

实现文件上传的几种方式

通过这幅图我们看到在servlet中我们需要用到一个名曰DiskFileItemFactory的类,他它帮助我们处理request的请求,而构造它的一个步骤如下:

实现文件上传的几种方式

记住了这四个步骤,我们基本上就掌握了文件上传。在第四步中,我们使用IO流的方式读取和写入上传的文件就OK了。具体代码如下:

实现文件上传的几种方式

以上我们就基本上把本章的上传片讲完了。回顾以下,我们讲过了struts的上传,cos上传,最后是commons上传。在这里我仍然还是要讲一个东西,就是不论是哪种上传方式,我们都需要注意的几点问题:

实现文件上传的几种方式

一般而言,服务器都会为自动提供一个缓冲目录,当然如果服务器不存在还是需要我们自己去手动创建。

实现文件上传的几种方式



实现文件上传的几种方式



实现文件上传的几种方式



实现文件上传的几种方式



实现文件上传的几种方式

补充:struts2中集成了文件下载的功能,只要在result的type中配置为stream流的类型就表示该结果以流的方式返回到客户端,完成下载。

小结:

本章内容讲解了项目经常有的需求即文件的上传,讲了很多种不同类型的上传机制以及上传过程中我们需要注意的几个问题。

ICP备案号:苏ICP备14035786号-1 苏公网安备 32050502001014号