本章内容
7.1 FileUpload文件上传控件
7.2 TextBox的自动完成(AutoCompleteType)改良
7.3 DropDownList控件的AppendDataBoundItems属性
7.4 Panel控件的滚动条
7.5 MultiView与View控件
7.6 Wizard向导控件
7.7 结论
本章将介绍ASP.NET 2.0其他既有控件的改良或新增,主要包括了:
l FileUpload文件上传控件
l TextBox的自动完成(AutoCompleteType)改良
l DropDownList控件的AppendDataBoundItems属性
l Panel控件的滚动条
l MultiView与View控件
l Wizard向导控件
通过对这些控件新功能的运用,您在设计程序时将会更顺手。
7.1 FileUpload文件上传控件
以往ASP.NET 1.0只能使用Client端的Input(File)进行文件上传,但功能略为简单;而ASP.NET 2.0则内置了服务器端的FileUpload文件上传控件,它的功能比Input(File)功能更丰富更强大。FileUpload向控件程序员提供了更大的操控性,让程序员可以介入到更底层的操控,这是Input(File)所不及的。
范例7-1 FileUpload控件上传文件
让我们先实现第一个FileUpload范例,熟悉它如何运作后,再来深入了解更多细部功能。请参考FileUpload.aspx程序,步骤说明如下:
添加消息显示Label
请添加两个Label,一个作为指定文件标题显示,另一个当作上传完成消息显示。
创建FileUpload控件
请拖曳一个FileUpload控件到Page页面,FileUpload控件本身只提供文件的选取功能,而实际开始执行文件上传操作则必须另行创建一个Button按钮Click来触发(见图7-1)。
加入上传Button按钮
由于FileUpload控件必须由用户触发才会开始进行上传操作,故在此创建一个Button按钮控件,并双击Button按钮加入Click事件程序。
01 '文件上传
02 Protected Sub btnUpload_Click(ByVal sender As Object, ByVal e As
System.EventArgs) Handles btnUpload.Click
03 '检查是否有文件
04 If FileUpload1.HasFile Then
05 Try
06 '获取网站根目录路径
07
Dim path As String =
HttpContext.Current.Request.MapPath("~/")
08 '存储文件到磁盘
09 FileUpload1.SaveAs(path & FileUpload1.FileName)
10
11 txtMsg.Text = "文件名称:" & FileUpload1.PostedFile.FileName
& "<br>"
12
txtMsg.Text += "文件大小:" &
FileUpload1.PostedFile.ContentLength & "
Bytes<br>"
13
txtMsg.Text += "文件类型:" &
FileUpload1.PostedFile.ContentType &
"<br>"
14
15 Catch ex As Exception
16 txtMsg.Text = ex.Message.ToString()
17 End Try
18 Else
19 txtMsg.Text = "必须指定文件!"
20 End If
21 End Sub

图7-1 拖曳FileUpload控件
程序说明:
(1)FileUpload1.HasFile用来检查FileUpload是否有指定文件。
(2)HttpContext.Current.Request.MapPath("~/") 则是获取网站所在的磁盘绝对路径的,如C:\Inetpub\ServerControls\路径,之所以要这么做,是因为FileUpload控件必须指定“绝对路径”,而非相对路径,同时绝对路径也必须有写入权限。
(3)FileUpload1.SaveAs()则是将上传文件存储在磁盘的方法。
(4)FileUpload1.FileName用于获取上传文件名称。
(5)FileUpload1.PostedFile.ContentLength用于获取上传文件大小,以Byte为单位。
(6)FileUpload1.PostedFile.ContentType用于获取上传文件的类型(见图7-2)。

图7-2 FileUpload单一文件上传
各位可以看到, 虽然FileUpload控件只是一个服务器端的控件,然而它真正精彩的地方在于Button的Click事件程序代码。通过事件程序代码,您可以操纵文件上传后的各种行为模式,因而赋予程序员更大的弹性发挥空间。
在上传文件过程中,若您上传大型文件(例如10MB),上传会报错并中断,发生这种问题的原因在于系统默认限制上传文件大小为4096KB,故只要上传超过这个限制就会产生错误并中断,那怎么办?若您想要解除这层限制,就必须调整maxRequestLength长度限制,请在Web.Config文件中加入下列设置:
<configuration>
<system.web>
<httpRuntime maxRequestLength="4096" executionTimeout="120"/>
</system.web>
</configuration>
设置说明:
(1)maxRequestLength这个属性限制文件上传的大小,是以KB为单位的,默认值为4096KB,而最大上限为2097151KB,大约是2GB。
(2)executionTimeout属性则是限制文件上传的时间,以秒(s)为单位,默认值为90 s,如果您考虑到所设计的Web应用系统上传时间要超过90 s可延长设定值。
范例7-2 FileUpload多个文件上传
第一个FileUpload范例只提供了一个文件上传,但若是要一次上传多个文件该如何做呢?简单一点的做法是多创建几个FileUpload控件,然后一次上传。事实上,许多世界级入口网站也是采用这样的方式。请参考FileUploadMulti.aspx程序,步骤说明如下:
创建画面Layout及相关控件
请创建相关控件配置,并添加10个FileUpload控件,完成后画面如图7-3所示。

图7-3 FileUpload多文件上传画面配置
加入上传程序
一次上传多个文件要比只上传一个文件需要更多的防呆程序,且也要多用几个小技巧来避免写一堆重复性的程序代码。请在【文件上传】按钮的Click事件加入下列相关程序:
01 '文件上传
02 Protected Sub btnUpload_Click(ByVal sender As Object, ByVal e As
System.EventArgs) Handles btnUpload.Click
03 txtMsg.Text = ""
04 Try
05 Upload(FileUpload1)
06 Upload(FileUpload2)
07 Upload(FileUpload3)
08 Upload(FileUpload4)
09 Upload(FileUpload5)
10 Upload(FileUpload6)
11 Upload(FileUpload7)
12 Upload(FileUpload8)
13 Upload(FileUpload9)
14 Upload(FileUpload10)
15
16 txtMsg.Text =
"完成文件上传如下:<BR>" &
ViewState("Uploads").ToString()
17 ViewState("Uploads") = Nothing
18 Catch ex As Exception
19 txtMsg.Text = ex.Message
20 End Try
21 End Sub
22
23 '上传文件方法
24 Protected Sub Upload(ByVal myFileUpload As
System.Web.UI.WebControls.FileUpload)
25 '获取网站根目录路径
26 Dim path As String = HttpContext.Current.Request.MapPath("~/")
27 '检查是否有文件
28 If (myFileUpload.HasFile) Then
29 Try
30 '存储文件到磁盘
31 myFileUpload.SaveAs(path & myFileUpload.FileName)
32
ViewState("Uploads") +=
myFileUpload.PostedFile.FileName.ToString() &
"<br>"
33 Catch ex As Exception
34 txtMsg.Text += ex.Message.ToString()
35 End Try
36 Else
37 '检查至少必须指定一个上传文件
38 If hasFile() Then
39 txtMsg.Text = "必须指定文件!"
40 End If
41 End If
42 End Sub
43
44 '检查是否有文件,若十个FileUpload控件无指定文件则返回False
45 Protected Function hasFile() As Boolean
46 'status为检查FileUpload是否含文件,默认为False,若有文件则为True
47 Dim status As Boolean = False
48 status = FileUpload1.HasFile Or
FileUpload2.HasFile Or
FileUpload3.HasFile
_
49 Or FileUpload4.HasFile Or FileUpload5.HasFile Or FileUpload6.HasFile _
Or FileUpload7.HasFile Or FileUpload8.HasFile Or FileUpload9.HasFile Or _
50 FileUpload10.HasFile
51
52 '以上写法等同下面写法
53 'status = FileUpload1.HasFile
54 'status = FileUpload2.HasFile
55 'status = FileUpload3.HasFile
56 'status = FileUpload4.HasFile
57 'status = FileUpload5.HasFile
58 'status = FileUpload6.HasFile
59 'status = FileUpload7.HasFile
60 'status = FileUpload8.HasFile
61 'status = FileUpload9.HasFile
62 'status = FileUpload10.HasFile
63
64 Return status
65 End Function
加入显示Web.config上传文件大小
由于多个文件上传会涉及Web.config中maxRequestLength文件上传的大小,故有必要让用户知道系统目前限制值为多少。请先引用System.Web.Configuration命名空间,而后在Page_Load中加入下列程序:
01 Imports System.Web.Configuration
02 ...略
03 Protected Sub Page_Load(ByVal sender As Object, ByVal e As
System.EventArgs) Handles Me.Load
04 If (Not IsPostBack) Then
05 '开启网站的Web.config配置文件
06 Dim config As Configuration =
WebConfigurationManager.OpenWebConfiguration(Me.Request.ApplicationPath)
07 '获取system.web/httpRuntime配置区块
08 Dim myHttpRuntimeSection As HttpRuntimeSection = CType(config.GetSection("system.web/httpRuntime"), HttpRuntimeSection)
09 '获取MaxRequestLength设置值大小
10 txtFileSize.Text = "(文件上传总和最大限制为" & String.Format("{0:N0}",
CType(myHttpRuntimeSection.MaxRequestLength, Int32)) & "KB大小)"
11 FileUpload1.Focus()
12 End If
13 End Sub
设置maxRequestLength
请将原先的maxRequestLength改为100000(KB)。之所以这么做,是因为连祭司都以为它设限针对的是单一文件,但是经过反复测试才知道它是针对整个页面的所有上传文件总和的,所以您必须衡量您Web应用程序多文件上传的总容量,再设置一个最佳值。
<configuration>
<system.web>
<httpRuntime maxRequestLength="100000" executionTimeout="120"/>
</system.web>
</configuration>
完成后请进行测试。祭司分别找了3个不同大小的文件(7MB、13MB、23MB)来进行测试,并且不按顺序指定FileUpload控件的上传文件,目的是为了测试防呆是否起作用,执行画面如图7-4所示。

图7-4 FileUpload多个文件上传执行画面
注
根据祭司的测试发现,多个文件上传“似乎”是以异步的方式进行的,也就是说假设上传十个文件,并非上传完一个再上传下一个文件,而是十个文件同时上传,由于同时有十个FileUpload实体在各自进行数据上传及写入磁盘操作,且一旦上传操作开始,您就无法通过关闭IE来终止(请用大型文件测试便知),必须关闭IIS的Process才行,在此跟各位分享这个心得。
范例7-3 限制FileUpload文件的上传类型
OK,多个文件上传各位已经会了,那想必有人会问:“是否可以限制文件上传类型?”比如说限制上传类型为 .doc、.xls、.ppt、.jpg、.gif这5种,该怎么做呢?在此将上一个范例修改扩充,请参考FileUploadExtension.aspx程序,完整程序代码如下:
01 Imports System.Web.Configuration
02
03 Partial Class FileUploadExtension
04 Inherits System.Web.UI.Page
05
06 Protected Sub Page_Load(ByVal sender As Object, ByVal e As
System.EventArgs) Handles Me.Load
07 If (Not IsPostBack) Then
08 '开启网站的Web.config配置文件
09 Dim config As Configuration =
WebConfigurationManager.OpenWebConfiguration(Me.Request.ApplicationPath)
10 '获取system.web/httpRuntime配置区块
11
Dim myHttpRuntimeSection As HttpRuntimeSection =
CType(config.GetSection("system.web/httpRuntime"),
HttpRuntimeSection)
12 '获取MaxRequestLength设置值大小
13
txtFileSize.Text = "(文件上传总和最大限制为" &
String.Format("{0:N0}",
CType(myHttpRuntimeSection.MaxRequestLength, Int32)) & "KB大小)"
14 FileUpload1.Focus()
15 End If
16 End Sub
17
18 Protected Sub btnUpload_Click(ByVal
sender As Object, ByVal e As
System.EventArgs)
Handles btnUpload.Click
19 txtMsg.Text = ""
20 Try
21 Upload(FileUpload1)
22 Upload(FileUpload2)
23 Upload(FileUpload3)
24 Upload(FileUpload4)
25 Upload(FileUpload5)
26 Upload(FileUpload6)
27 Upload(FileUpload7)
28 Upload(FileUpload8)
29 Upload(FileUpload9)
30 Upload(FileUpload10)
31
32
txtMsg.Text = "完成文件上传如下:<BR>" &
ViewState("Uploads").ToString()
33 ViewState("Uploads") = Nothing
34 Catch ex As Exception
35 txtMsg.Text = ex.Message
36 End Try
37 End Sub
38
39 '上传文件方法
40 Protected Sub Upload(ByVal myFileUpload
As
System.Web.UI.WebControls.FileUpload)
41 '是否允许上传
42 Dim fileAllow As Boolean = False
43 '设置允许上传的延伸文件名类型
44 Dim
allowExtensions() As String = {".doc", ".xls",
".ppt", ".jpg",
".gif"}
45
46 '获取网站根目录路径
47 Dim path As String = HttpContext.Current.Request.MapPath("~/")
48 '检查是否有文件
49 If (myFileUpload.HasFile) Then
50 '获取上传文件之延伸文件名,并转换成小写字母
51
Dim fileExtension As String =
System.IO.Path.GetExtension(myFileUpload.FileName).ToLower()
52 '检查延伸文件名是否符合限定类型
53 For I As Integer = 0 To allowExtensions.Length - 1
54 If (fileExtension = allowExtensions(I)) Then
55 fileAllow = True
56 Exit For
57 End If
58 Next
59
60 If fileAllow Then
61 Try
62 '存储文件到磁盘
63 myFileUpload.SaveAs(path & myFileUpload.FileName)
64
ViewState("Uploads") +=
myFileUpload.PostedFile.FileName.ToString() & "<br>"
65 Catch ex As Exception
66 txtMsg.Text += ex.Message.ToString()
67 End Try
68 Else
69
ViewState("Uploads") += "不允许上传:" &
myFileUpload.PostedFile.FileName & "<br>"
70 End If
71 Else
72 '检查至少必须指定一个上传文件
73 If hasFile() Then
74 txtMsg.Text = "必须指定文件!"
75 End If
76 End If
77 End Sub
78
79 '检查是否有文件,若十个FileUpload控件无指定文件则返回False
80 Protected Function hasFile() As Boolean
81 'status为检查FileUpload是否有文件,默认为False,若有文件则为True
82 Dim status As Boolean = False
83 status =
FileUpload1.HasFile Or FileUpload2.HasFile Or
FileUpload3.HasFile _
84 Or
FileUpload4.HasFile Or FileUpload5.HasFile Or
FileUpload6.HasFile _
85 Or
FileUpload7.HasFile Or FileUpload8.HasFile Or
FileUpload9.HasFile Or _
86 FileUpload10.HasFile
87
88 '以上写法等同下面写法
89 'status = FileUpload1.HasFile
90 'status = FileUpload2.HasFile
91 'status = FileUpload3.HasFile
92 'status = FileUpload4.HasFile
93 'status = FileUpload5.HasFile
94 'status = FileUpload6.HasFile
95 'status = FileUpload7.HasFile
96 'status = FileUpload8.HasFile
97 'status = FileUpload9.HasFile
98 'status = FileUpload10.HasFile
99
100 Return status
101 End Function
102 End Class
程序说明:
这个程序的主体是修改扩充Protected Sub Upload(ByVal myFileUpload As System.Web.UI.WebControls.FileUpload)这种方法,程序中都有详细技巧说明批注,在此不赘述。
完成后请执行测试,祭司一共上传5个文件,其中故意加入不合规定的.txt文件类型,结果当然是会被系统检测到,所有文件都上传成功,惟独.txt没有上传,执行画面如图7-5所示。
在举例说明FileUpload控件的诸多用法后,相信这些用法已足以应付一般常见的文件上传情况。但祭司要说的是:在我第一眼看到FileUpload控件时,心中就有个疑惑:“就这样?”即使不用FileUpload控件,大家用传统技巧也能够做出来,心里想:“微软开发小组吃饱了没事做,去把Client端改成Server端控件?”感觉有点把大家当成3岁小孩耍着玩的味道!但后来还是认为根本不可能是这样的,最后一次偶然的灵光一现,终于发现FileUpload控件的精妙之处:利用FileUpload控件再搭配Atlas Framework,可以做出“真实的”实时上传进度监控和已上传Bytes数的实时变化,这才是FileUpload控件画龙点睛之笔,但这部分要挪到下册才会再谈,不是要吊各位胃口,而是由于一方面篇幅不够,另一方面是超过本书截稿时间已经太长,故只好挪到下册再讨论。

图7-5 FileUpload限制文件上传类型






