技术背景
文件上传是JaveWeb开发者经常遇到的一个功能,目前文件上传的技术也是五花八门,这其中Apache旗下的commons-fileupload组件是使用比较广泛的一个文件上传的开源组件,基于commons-fileupload实现文件上传操作简单,并且commons-fileupload还提供了文件获得文件上传进度的接口,基于此,开发者就可以在页面上实时动态的显示文件上传的进度,很大程度提高用户的体验。
·
技术分析
文件上传的三要素
1.表单的提交方式必须为POST方式
2.表单中提供文件项
3.将表单的enctype设置为multipart/form-data
文件上传的步骤
1.创建磁盘文件工厂对象
2.创建核心的解析类对象
3.设置监听文件上传进度的监听器,以便获得文件上传的进度
4.解析请求,获得表单项的集合对象
5.遍历表单项的集合
6.判断当前的表单项是否是文件项
6.1.如果是普通文本项,获得参数的名称和值
6.2.如果是文件项,获取文件内容,使用流写入到服务器磁盘中
1.表单的提交方式必须为POST方式
2.表单中提供文件项
3.将表单的enctype设置为multipart/form-data
文件上传的步骤
1.创建磁盘文件工厂对象
2.创建核心的解析类对象
3.设置监听文件上传进度的监听器,以便获得文件上传的进度
4.解析请求,获得表单项的集合对象
5.遍历表单项的集合
6.判断当前的表单项是否是文件项
6.1.如果是普通文本项,获得参数的名称和值
6.2.如果是文件项,获取文件内容,使用流写入到服务器磁盘中
·
进度条功能分析
页面上动态变化的进度条其实是一个具有背景色的div块,让这个div块的宽度随着文件上传的进度的多少而变化就是进度条。这其中要解决的问题是如何实时获得文件上传的进度,并且页面在文件没有上传结束前不能跳转。显然,此时要从服务器获得文件上传的进度必须使用异步请求的方式。服务器端可以将当前文件上传的进度放置在Session域中,前台间隔一段时间通过Ajax异步的方式从服务器端的Session中获得文件上传的进度,并更新div的宽度。
HTML代码
Javascript代码
Java代码
FileUploadServlet.java
ShowFileUploadProgress.java
FileUtils.java
HTML代码
[HTML]
纯文本查看
复制代码
01
02
03
04
05
06
07
08
09
10
|
<
body
>
<!-- 进度条的DIV -->
<
div
id
=
"div1"
style
=
"background-color: red;height: 20px;width: 0"
></
div
>
<!-- 表单 -->
<
form
action
=
"${pageContext.request.contextPath }/FileUploadServlet"
method
=
"post"
enctype
=
"multipart/form-data"
>
[font=宋体]文件描述[/font]:<
input
type
=
"text"
name
=
"desc"
><
br
/>
[font=宋体]文件[/font]:<
input
type
=
"file"
name
=
"file"
><
br
/>
<
input
type
=
"submit"
value
=
"提交"
>
</
form
>
</
body
>
|
Javascript代码
[JavaScript]
纯文本查看
复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
|
<script type=
"text/javascript"
src=
"${pageContext.request.contextPath }/js/jquery-1.8.3.js"
></script>
<script type=
"text/javascript"
>
$(
function
(){
$(
"#div1"
).css(
"width"
,
"0"
);
setInterval(
"showProgress()"
,10);
});
//显示文件上传的进度
function
showProgress(){
$.get(
"${pageContext.request.contextPath}/ShowFileUploadProgress"
,
function
(data){
$(
"#div1"
).css(
"width"
,data);
})
}
</script>
|
Java代码
FileUploadServlet.java
[Java]
纯文本查看
复制代码
01
02
03
04
05
06
07
08
09
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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
|
import
java.io.File;
import
java.io.FileOutputStream;
import
java.io.IOException;
import
java.io.InputStream;
import
java.text.NumberFormat;
import
java.util.List;
import
javax.servlet.ServletException;
import
javax.servlet.http.HttpServlet;
import
javax.servlet.http.HttpServletRequest;
import
javax.servlet.http.HttpServletResponse;
import
org.apache.commons.fileupload.FileItem;
import
org.apache.commons.fileupload.FileUploadException;
import
org.apache.commons.fileupload.ProgressListener;
import
org.apache.commons.fileupload.disk.DiskFileItem;
import
org.apache.commons.fileupload.disk.DiskFileItemFactory;
import
org.apache.commons.fileupload.servlet.ServletFileUpload;
import
org.apache.commons.io.IOUtils;
import
cn.itcast.utils.FileUtils;
/**
* 文件上传的Servlet
*/
@SuppressWarnings
(
"all"
)
public
class
FileUploadServlet
extends
HttpServlet {
protected
void
doGet(
final
HttpServletRequest request, HttpServletResponse response) {
try
{
//1.创建磁盘文件工厂对象
DiskFileItemFactory diskFileItemFactory =
new
DiskFileItemFactory();
//2.创建核心的解析类对象
ServletFileUpload fileUpload =
new
ServletFileUpload(diskFileItemFactory);
//3.设置监听文件上传进度的监听器,以便获得文件上传的进度
fileUpload.setProgressListener(
new
ProgressListener() {
@Override
public
void
update(
long
pBytesRead,
long
pContentLength,
int
pItems) {
double
pRead = pBytesRead;
double
pLength = pContentLength;
//获得数字格式化对象--百分比
NumberFormat format = NumberFormat.getPercentInstance();
//保留2位小数点
format.setMaximumFractionDigits(
2
);
//计算文件上传的进度
String percent = format.format(pRead/pLength);
System.out.println(
"已经上传的进度:"
+percent);
//将文件上传的进度保存在Session域中
request.getSession().setAttribute(
"progress"
, percent);
}
});
//解决中文文件名上传的乱码的问题
fileUpload.setHeaderEncoding(
"UTF-8"
);
//4.解析请求,获得表单项的集合对象
List<FileItem> list = fileUpload.parseRequest(request);
//5.遍历表单项的集合
for
(FileItem fileItem : list) {
//6.判断当前的表单项是否是文件项
if
(fileItem.isFormField()){
//6.1.如果是普通文本项,获得参数的名称和值
String name = fileItem.getFieldName();
String value = fileItem.getString(
"UTF-8"
);
System.out.println(name+
":"
+value);
}
else
{
//6.2.如果是文件项,获取文件内容,使用流写入到服务器磁盘中
String fileName = fileItem.getName();
//文本保存的根目录
String baseDir =
"C:\\Users\\fudingcheng\\Desktop\\file"
;
//获得文件保存子目录
String childDir = FileUtils.getDirNameByDate();
//判断子目录是否存在
File realDir =
new
File(baseDir+childDir);
if
(!realDir.exists()){
realDir.mkdirs();
}
//将文件写到磁盘中
fileItem.write(
new
File(baseDir+childDir, fileName));
}
}
}
catch
(Exception e) {
e.printStackTrace();
}
}
protected
void
doPost(HttpServletRequest request, HttpServletResponse response)
throws
ServletException, IOException {
doGet(request, response);
}
}
|
ShowFileUploadProgress.java
[Java]
纯文本查看
复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
import
java.io.IOException;
import
javax.servlet.ServletException;
import
javax.servlet.http.HttpServlet;
import
javax.servlet.http.HttpServletRequest;
import
javax.servlet.http.HttpServletResponse;
/**
* 获取文件上传进度的Servlet
*/
@SuppressWarnings
(
"serial"
)
public
class
ShowFileUploadProgress
extends
HttpServlet {
protected
void
doGet(HttpServletRequest request, HttpServletResponse response)
throws
ServletException, IOException {
String percent = (String) request.getSession().getAttribute(
"progress"
);
response.getWriter().print(percent);
}
protected
void
doPost(HttpServletRequest request, HttpServletResponse response)
throws
ServletException, IOException {
// TODO Auto-generated method stub
doGet(request, response);
}
}
|
FileUtils.java
[Java]
纯文本查看
复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
|
import
java.util.Calendar;
/**
* 文件上传的工具类
*/
public
class
FileUtils {
/**
* 生成子目录的方法
*/
public
static
String getDirNameByDate(){
Calendar calendar = Calendar.getInstance();
int
year = calendar.get(Calendar.YEAR);
int
month = calendar.get(Calendar.MONTH)+
1
;
int
day = calendar.get(Calendar.DAY_OF_MONTH);
return
"/"
+year+
"/"
+month+
"/"
+day;
}
}
|
效果图展示