一、Uploadify控件
在ASP.NET中上传的控件有很多,比如.NET自带的FileUpload,以及SWFUpload,Uploadify等等,尤其后面两个控件的用户体验比较好,无刷新,带上传进度等等。在最近的一个webform开发项目中,我就是使用的Uploadify,虽然有些小瑕疵,但是基本上还是满意的(在webform中使用Uploadify可以参考《JQuery上传插件Uploadify使用详解》),所以当现在使用MVC开发的时候,自然将之作为首选。
Uploadify官方Demo
二、在MVC中使用Uploadify
首先引入js和css文件:
<
script
src
="/Content/Scripts/jquery-1.4.1.min.js"
type
="text/javascript"
></
script
>
<
script
src
="/Content/Scripts/swfobject.js"
type
="text/javascript"
></
script
>
<
script
src
="/Content/Scripts/jquery.uploadify.v2.1.0.min.js"
type
="text/javascript"
></
script
>
<
link
href
="/Content/Styles/uploadify.css"
rel
="stylesheet"
type
="text/css"
/>
在页面上放一个最普通的file控件(其中checkImport是我自己写的一个验证方法,当没有选择上传文件的时候警告):
<
div
>
<
p
><
input
id
="fileInput1"
name
="fileInput1"
type
="file"
/></
p
>
<
p
style
="margin-top:5px;font-size:14px;font-weight:bold;"
>
<
a
href
="javascript:if(checkImport()){$('#fileInput1').uploadifyUpload();}"
>
导入文件
</
a
></
p
>
<
p
style
="margin-top:5px;font-size:14px;font-weight:bold;"
><
span
id
="result"
></
span
></
p
>
</
div
>
然后就可以加入如下js,其中script就是请求服务器的一个处理地址,在webform中通常是指向一个aspx或者ashx文件,在MVC中则是请求一个action,比如这里就是请求ExcelController的Import方法(我的路由是"Admin/{controller}/{action}/{id}"):
$(
function
() {
//
上传
$(
'
#fileInput1
'
).uploadify({
'
uploader
'
:
'
/Content/Images/uploadify.swf
'
,
'
script
'
:
'
/Admin/Excel/Import
'
,
'
folder
'
:
'
/UploadFiles
'
,
'
cancelImg
'
:
'
/Content/Images/cancel.png
'
,
'
fileExt
'
:
'
*.xls
'
,
'
fileDesc
'
:
'
*.xls
'
,
'
sizeLimit
'
:
1024
*
1024
*
4
,
//
4M
'
multi
'
:
false
,
'
onComplete
'
: fun });
});
function
fun(event, queueID, fileObj, response, data) {
if
(response
!=
""
) { showInfo(
"成功上传
"+response
,
true
); //showInfo方法设置上传结果 }
else
{ showInfo(
"
文件上传出错!
"
,
false
); } }
在对应的ExcelController中就可以这么写:
[AcceptVerbs(HttpVerbs.Post)]
public
ContentResult Import(HttpPostedFileBase FileData,
string
folder) {
string
result
=
""
;
if
(
null
!=
FileData) {
try
{ result
=
Path.GetFileName(FileData.FileName);
//
获得文件名
string
ext
=
Path.GetExtension(FileData.FileName);
//
获得文件扩展名
string
saveName
=
"
uploadfile
"
+
ext;
//
实际保存文件名
saveFile(FileData, folder, saveName);
//
保存文件
}
catch
{ result
=
""
; } }
return
Content(result); }
[NonAction]
private
void
saveFile(HttpPostedFileBase postedFile,
string
filepath,
string
saveName) {
string
phyPath
=
Request.MapPath(
"
~
"
+
filepath
+
"
/
"
);
if
(
!
Directory.Exists(phyPath)) { Directory.CreateDirectory(phyPath); }
try
{ postedFile.SaveAs(phyPath
+
saveName); }
catch
(Exception e) {
throw
new
ApplicationException(e.Message);
} }
注意两个参数FileData和folder都是固定名称的,并且FileData的参数类型是HttpPostedFileBase而不是HttpPostedFile(我刚开始就是在这里纠结很久,总是取不到文件),关于为什么要使用HttpPostedFileBase,我在网上找到这样一段话,看来是由于单元测试的原因吧。。。
Just work with it
as
an HttpPostedFileBase. The framework uses the HttpPostedFileWrapper
to convert an HttpPostedFile to an
object
of HttpPostedFileBase. HttpPostedFile
is
one
of those
sealed
classes that are hard to unit test with. I suspect that sometime
after
the example was written they applied the wrapper code to improve the ability
to test
(
using
HttpPostedFileBase) controllers
in
the MVC framework. Similar things
have been
done with the HttpContext, HttpRequest, and HttpReponse properties on
the controller.
成功上传文件后的效果如下:
实例程序下载