1.需求分析:
(1)可以选择上传文件类型,限制上传文件大小,实现单个或多个文件同时上传功能,在上传过程中显示文件上传进度比例信息。
(2)文件成功上传后,如果是图片文件,则可以进行图片预览功能。
(3)无论是单个或多个文件成功上传后,可删除其队列中的某一个文件。
2.界面效果:
选择单个或多个文件上传时,显示带百分比的进度条,提示文件上传进度信息。文件上传成功后,通过回调函数可以返回上传文件的URL。这个URL地址如果是图片,可以实现图片预览的功能。在文件上传成功后预览图片时,选择某个文件,单击"删除"链接,可以删除指定的某个上传后的文件。
3.插件介绍:
在这个案例中,使用了基于jQuery库开发的上传文件插件uploadify。该插件是众多插件中较为优秀的一款,支持多文件自动上传,带上传进度条和百分比例,并支持多种函数触发事件,如函数onComplete(完成后),onError(出错时)等。该插件广泛应用于各项目中,深受开发者的喜爱。
在本案例中,使用了uploadify插件的一些属性和函数,该插件的核心方法是uploadify(),其调用的格式如下:
$(上传文件元素).uploadify(options)
options对象包含的常用属性
参数名称 | 功能描述 |
uploader | 上传控件的主体文件,一个Flash控件,默认值"uploadify.swl"。 |
script | 相对路径的服务端文件名,它将处理上传的文件,绝对路径前缀或"/"或"http"的路径。默认值为"uploadify.php"。 |
folder | 上传文件保存在服务器端的路径。 |
queueID | 上传文件的队列ID号,与客户端页的ID号相同。 |
queueSizeLimit | 设置在一次队列中的文件总数,单击"浏览"按钮后,可以同时选择多少个文件。 |
multi | 是否允许同时上床多文件,可设定true或false。默认值为false。 |
auto | 选定文件后是否自动上传,可设定true或false。默认值为false。 |
fileDesc | 出现在上传对话框中,对文件类型描述,必须与fileExt结合使用才有效。 |
fileExt | 上传文件所支持的格式,启用本项时需要同时声明fileDesc。如"*.jpg,*.bmp,*gif"。 |
sizeLimit | 设置上传文件的最大值,单位为字节。 |
simUploadLimit | 在多个文件上传时,设置同时上传文件数目。默认值为1。 |
buttonText | 默认选择上传文件按钮的文字。默认值为BROWER。 |
buttonImg | 默认选择上传文件按钮的图片地址。 |
onInit | 该函数用于检测上传文件时的初始状态,使用方法如下: onInit:function(){$("#id").html("正在初始化...");} |
onComplete | 该函数用于文件上成功后触发,可传回5个参数。 |
onSelect | 该函数用于选择文件后触发,可传回3个参数event,queueID,fileObj,各参数代表的意义与onComplete。 |
onError | 该函数用于选择文件上传出错后触发,可传回4个参数event,queueID,fileObj,errorObj。其中前三个参数与onComplete函数一样,errorObj参数有两个属性:一个是type,表示错误类型,有三个类型,即"HTTP","IO","Security";另一个属性是info,表示错误的信息描述。 |
(1)插件文件:
Js/jquery.uploadify.v2.1.0.js
Js/swfobject.js
Images/全部文件
Css/uploadify.css
(2)下载地址:
http://www.uploadify.com/download/
4.功能实现:
上传文件插件uploadify下载完成后,其使用方法十分简单,下面介绍其使用的步骤:
(1)在调用文件中引用两个JS文件:jquery.uploadify.v2.1.0.js用于文件的上传,swfobject.js用于选择上传文件的按钮。其实现代码如下:
<script type="text/javascript" src="Js/swfobject.js"></script>
<script type="text/javascript" src="Js/jquery.uploadify.v2.1.0.js"></script>
(2)在引用插件的页面中编写JS代码,设置uploadify插件上传文件时必须使用的属性,如保存上传文件的地址,处理文件上传的服务器端文件名等。其实现代码如下:
$(function(){
$("#uploadify").uploadify({
'uploader':'Images/uploadify.swf',
'script':'Deal/UploadFile.ashx',
'cancelImg':'Images/cancel.png',
'folder':'Uploads/',
'queueID':'fileQueue',
'buttonImg':'Images/uploadify.jpg',
'auto':true,
'multi':true,
})
})
在上述JS代码中,为了不使用插件默认的选择上传文件的按钮,我们调用了一个"buttonImg"属性,并通过该属性设置自己定义的按钮地址,为确保文件的正确上传,其他属性所指定的文件路径或ID号必须准确无误。
(3)当插件的JS文件被引用并且相关的基本属性设置完成之后,在引用的页面文件中加入如下的HTML代码,用于实现上传文件的选择和上传队列进度信息的展示:
<div id="fileQueue"></div>
<input type="file" name="uploadify" id="uploadify" />
其中,<div>标记的ID号与JS代码中"queueID"属性的值相同的,该属性表示上传文件对的ID号,即ID号为"fileQueue"的<div>标记用于存放上传文件的队列,并通过下列代码使页面中ID号为"uploadify"的文件上传元素与插件中的uploadify()方法相绑定:
$("#uploadify").uploadify({...})
(4)编写处理文件上传的服务器端代码
要实现文件的真正上传,还需要编写一个简单的服务端文件,接受传来的文件队列,逐个保存在服务器。在这个案例中,通过程序处理文件UploadFile.ashx实现上述的功能。实现代码如下:
<%@ WebHandler Language="C#" Class="UploadFile" %>
using System;
using System.IO;
using System.Web;
public class UploadFile:IHttpHandler{
public void ProcessRequest(HttpContext context)
{
context.Response.ContentType = "text/plain";
context.Response.Charset = "utf-8";
HttpPostedFile file = content.Request.Files["Filedata"];
//获取传回的保存文件地址
string uploadPath = HttpContext.Current
.Server.MapPath(@context.Request["folder"]) + "\\";
//如果有文件
if (file != null)
{
if (!Directory.Exists(uploadPath)) //目录不存在
{
Directory.CreateDirectory(uploadPath); //新创建目录
}
file.SaveAs(uploadPath + file.FileName);
//返回一个值,确保上传成功后,在前台的文件队列自动消失
context.Response.Write("1");
}
else
{
context.Response.Write("0");
}
}
...
}
(5)代码分析
经过上述四个步骤,就可以在一个HTML页面中通过引用uploadify插件中的方法,实现一个或多个文件的上传。
在通过uploadify插件实现文件上传过程中有一个onComplete()函数,该函数在每一个文件上传成功后便触发,并且在触发时传回5个参数,分别为event,queueId,fileObj,response,data,其各自代码意义如下:
event:表示触发事件的对象。
queueId:上传文件中队列的标识,用于区分每一个上传文件,它由六位随机数组组成。
fileObj:选择上传的文件对象。通过该对象,可以访问上传文件的相关属性,如name(名称),size(大小),creationDate(创建时间),modificationDate(修改时间),type(文件类型),filePath(保存路径)。
response:服务器端文件上传处理程序返回的值,即文件UploadFile.ashx返回值。在本案例中,文件上传成功后,返回值为1.。
data:表示文件上传数据流。该对象有两个重要属性,一个是fileCount,表示还没有上传完的文件总量;另一个是speed表示文件的平均上传速度。
根据对onComplete()函数中各个返回参数的描述,可以通过第三个参数fileObj中的filePath属性值,返回上传文件后的URL。如果是图片上传,将返回的图片URL设置为客户端中<img>标记的src属性值,从而实现图片上传后预览的功能。其实现的JS代码如下:
function SetFileContent(objFile) { //根据上传对象返回预览的图片
var sLi = "";
sLi += "<li>";
sLi += "<img src='" + objFile.filePath + "'width='100' height='100'>";
sLi += "<input type='hidden' value='" + objFile.filePath + "'>";
sLi += "<br />";
sLi += "<a href='javascript:void(0)'>删除</a>";
sLi += "</li>";
return sLi;
}
其中,自定义的函数SetFileContent中的参数objFile就是onComplete()函数中的第三个参数fileObj,将上述函数SetFileContent放入onComplete()事件中,即实现了图片文件上传成功后,可以进行预览的功能,从而完成了第二项需求。其实现的代码如下:
$(function() {
$("#uploadify").uploadify({
...
'onComplete':function(event,queueID,fileObj,response,data) {
$('ul').append(SetFileContent(fileObj));
}
})
})
为了在页面中展示预览的图片,需要加入一个列表<ul>标记,其页面代码如下:
<ul></ul>
<div id="fileQueue"></div>
<input type="file" name="uploadify" id="uploadify" />
图片上传成功后进行预览时,为了可以删除不太理想的图片文件,需要确定被删除表项<li>的ID号,使用jQuery中的remove()方法移除指定的表项<li>的ID号,使用jQuery中的remove()方法移除指定的表项。最后,在增加新表项内容时,重新分配表项的ID号,从而保证ID号的不重复。具体流程如下:
(1)通过each方法遍历全部的表项<li>并设置对应的ID号,代码如下:
//设置各表项ID号
$("ul li").each(function(l_i) {
$(this).attr("id","li_" + l_i);
})
(2)通过each方法遍历全部表项中"删除"链接,设置对应的"rel"属性,用于传递删除表项的ID号,其代码如下:
//设置各链接的rel属性值
$("ul li a").each(function(a_i) {
$(this).attr("rel",a_i);
})
(3)根据表项中"删除"链接中的"rel"属性,设置删除某个表项的单击事件,其实现的代码如下:
//设置各链的单击事件
$("ul li a").click(function() {
//通过自身的rel值,获取表项的ID号
var li_id = "#li_" + this.rel;
//根据ID号,删除某个表项
$(li_id).remove();
})
由于上述操作都在同一函数中触发,并且可以进行链写,因此将其封装到另外一个自定义的函数SetUploadFile中,其最后完整的代码如下:
function SetUploadFile() {
//设置各项表ID号
$("ul li").each(function(l_i){
$(this).attr("id","li_"+l_i);
})
//设置各链接的rel属性值
$("ul li a").each(function(a_i){
$(this).attr("rel",a_i);
}).click(function(){ //设置各项链接的单击事件
//通过自身的rel值,获取表项的ID号
var li_id = "#li_" + this.rel;
//根据ID号,删除某个表项
$(li_id).remove();
})
}
最后,将上述定义的函数SetUploadFile放入onComplete()函数中,就可以在预览上传图片时进行删除的操作,从而完成了第三项需求。其实现代码如下
$(function(){
$("#uploadify").uploadify({
...
'onComplete':function(event,queueID,fileObj,response,data) {
$('ul').append(SetFileContent(fileObj));
SetUploadFile();
}
})
})
为了更好地实现页面与代码的分离,本案例中创建一个HTML文件UploadPic.html,用于用户选择上传的文件,其完整的代码如下:
<script type="text/javascript" src="Js/fileUpload.js"></script>
<script type="text/javascript" src="Css/uploadify.css"></script>
<style type="text/css">
...
</style>
<div class="divFrame">
<div class="divTitle">
上传图片
</div>
<div class="divContent">
<ul></ul>
<div id="fileQueue" style="clear:both;padding-top:5px"></div>
<div style="padding-top:5px">
<input type="file" name="uploadify" id="uploadify" />
</div>
</div>
</div>
另外,新建一个JS文件fileUpload.js,用于实现页面中的文件上传和预览,以及删除上传的文件,其完整代码如下:
///<reference path="../Jscript/jquery-1.8.2.min.js"/>
///<reference path="../Js/swfobject.js"/>
///<reference path="../Js/jquery.uploadify.v2.1.0.js"/>
$(function(){
$("#uploadify").uploadify({
'uploader':'Images/uploadify.swf',
'script':'Deal/UplaodFile.ashx',
'cancelImg':'Images/cancel.png',
'folder':'Uploads/',
'queueID':'fileQueue',
'buttonImg':'Images/uploadify.jpg',
'auto':true,
'multi':true,
'fileExt':'*.jpg;'.jpeg;*.gif;*.png',
'onComplete':function(event,queueID.fileObj,response,data){
$('ul').append(SetFileContent(fileObj));
setUploadFile();
}
})
})
function SetFileContent(objFile) { //根据上传对象返回预览的图片
var sLi = "";
sLi += "<li>";
sLi += "<img src='" + objFile.filePath + "' width='100' height='100'>";
sLi += "<input type='hidden' value='" + objFile.filePath + "'>";
sLi += "<br />";
sLi += "<a href='javascript:void(0)'>删除</a>";
sLi += "<li>";
}
function SetUploadFile() {
//设置各表项ID号
$("ul li").each(function(l_i){
$(this).attr("id","li_" + l_i);
})
//设置各链接的rel属性值
$("ul li a").each(function(a_i) {
$(this).attr("id","li_" + l_i);
}).click(function() {//设置各链接的单击事件
//通过自身的rel值,获取表的ID号
var li_id = "#li_" + this.rel;
$(li_id).remove();
})
}