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();
    })
}