Java Web 开发中文件上传方法研究与实现
陈涛++黄艳峰
摘要:文件上传是Web开发中经常需要实现的功能,介绍了Java Web开发中主流的文件上传方法,包括SmartUpload和Commons FileUpload两种组件上传,以及Servlet 3.0支持的原生API文件上传。给出了三种方法实现文件上传的主要代码,并对三者在上传大文件时的效率进行了比较。
关键词:SmartUpload;Commons FileUpload;Servlet 3.0;文件上传;Java Web
中图分类号:TP311 文献标识码:A 文章编号:1009-3044(2016)11-0048-02
在Web应用开发中,文件上传是经常需要实现的功能,目前广为流传的方法是使用第三方的文件上传组件。具体在Java web开发领域,常用的上传组件有SmartUpload、Apache Commons FileUpload等。在最新的Servlet 3.0规范中,对文件上传提供了API的原生支持,这样就可以不再依赖任何第三方上传组件。本文将举例探讨以上三种文件上传方法的特点,最后从上传效率上给出三种方法的比较。
1 SmartUpload组件
SmartUpload是在Java Web开发中使用较多的一个文件上传下载组件,它的特点是使用非常简单,只需几行代码即可实现文件的上传下载,所以即使SmartUpload已经停止了更新,但直到今天依然是很多开发者的选择。
SmartUpload的API中主要包括SmartUpload、Files、File、Request等核心类。由于篇幅限制,本文就不再列出各个类的方法了,读者可自行上网查阅。下面举例说明该组件的使用方法。
1) 编写文件上传表单文件
文件上传表单使用属性值为file的input标记,注意表单必须以post方式提交,表单的enctype属性必须是multipart/form-data。该文件在三种文件上传方法中都需要用到。
2) 编写JSP文件实现文件上传
首先需要将下载的SmartUpload组件jar包拷贝至Web应用的WEB-INF\lib目录下,然后编写实现文件上传功能的JSP文件。文件上传核心代码如下:
注意不同浏览器的默认设置不同,IE浏览器默认提交文件的整个路径(可以在Internet安全设置更改为不包含本地路径),而火狐或谷歌浏览器默认只提交文件名,所以需要考虑可能包含路径的情况,把文件名从中提取出来。Commons FileUpload组件自身没有提供限制上传文件类型的方法,需要自行编码从文件名取出扩展名并与允许上传的文件扩展名进行比较,然后给出用户相应的错误提示。除了使用FileItem的write()方法保存文件外,还可以通过FileItem的getInputStream()方法获取文件输入流,然后再通过输出流保存至文件甚至是数据库。在上传文件时如果超出了文件大小限制,系统会抛出异常FileSizeLimitExceedException,此异常是FileUploadException异常的子类,所以可以捕获该异常,并在异常处理代码中给出用户错误提示。
3 Servlet 3.0文件上传
上述两种文件上传方法都需要用到第三方组件,而在最新的Servlet 3.0规范中,提供了对文件上传的原生支持,直接使用Servlet 3.0提供的API就能够轻松实现文件上传。较之Servlet2.5主要是增加了两个类:MultipartConfig和Part。其中MultipartConfig是注解类,要想让Servlet支持文件上传只需在其前面添加如下形式注解即可:
@MultipartConfig(maxFileSize=1024*1024*300) //设置单个文件最大上传大小,如300M
另外HttpServletRequest类还增加了一个getParts()方法,该方法可以获取表单提交过来的所有上传文件,这些文件信息封装在一个个的Part对象中。Part类提供了write方法用于保存上传的文件。在Servlet的doPost()方法编写如下代码:
for(Part part : request.getParts()) { //遍历所有上传的文件
String filename = getFilename(part); //自定义方法从请求头信息中得到文件名
File savePath = request.getServletContext().getRealPath(“upload\\”) + filename;
part.write(savePath); //保存上传的文件到指定的路径
}
因为Servlet 3.0没有提供直接获取文件名的方法,所以只能自行编写方法getFilename()从请求头中解析文件名。以火狐浏览器为例(若是IE,则文件名带路径),请求头格式为:
Content-Disposition: form-data; name="fileName"; filename="test.avi"。getFilename()方法代码如下:
private String getFilename(Part part) {
String contentDisp = part.getHeader("content-disposition");
String[] tokens = contentDisp.split(";");
for (String token : tokens) {
if (token.trim().startsWith("filename")) {
String filename = token.substring(token.indexOf("=") + 2, token.length()-1);
return filename.substring(filename.lastIndexOf("\\")+1); //兼容所有浏览器
}
}
return "";
}
如果上传文件违法大小限制,在获取Part对象时将抛出IllegalStateException异常,所以可以将以上for循环代码置入try-catch结构中,通过捕获IllegalStateException异常来判断文件是否超出大小限制。对于上传文件后缀的限制方法与Commons FileUpload组件一样,也是在得到的文件名中提取扩展名,再与允许上传的文件扩展名比较即可。
4 运行测试
分别运行以上三种文件上传程序,当上传体积较小文件时,三者在资源利用率及响应时间方面差别不太显著,但当增加上传文件大小时,例如上传300M左右的视频文件,经测试使用SmartUpload组件、Commons FileUpload组件、Servlet 3.0 API上传文件花费的平均时间分别为6.642s、5.174s、4.750s。从资源占用情况来看,Servlet 3.0 API文件上传也是最节约系统资源的方法。
5 结论
本文分析对比了目前Java Web开发中三种常见的文件上传方法,前两种方法需要借助第三方组件来实现,其中SmartUpload组件代码简单,实现方便,但目前已停止更新,并且在上传大文件时效率不高,而Commons FileUpload组件目前依然在更新维护中,上传大文件时有不错的性能,并且也被很多主流框架所使用。最后一种文件上传方法使用Servlet 3.0自身的API来实现,不再依赖第三方组件,上传效率比Commons FileUpload也更为高效,所以如果Java Web项目是基于Java EE 6以上版本开发的,建议考虑使用Servlet 3.0 API的文件上传方法。
参考文献:
[1] 张书锋.基于Java语言的文件上传组件研究[J].电脑知识与技术,2013(33).
[2] 刘杨. JSP项目开发常用文件上传组件比较及举例[J].电脑编程技巧及维护,2015(8).
[3] 周兵.基于JSP文件上传中的问题探讨及改进方案[J].兰州工业学院学报,2015(4).