javascript及php笔记:自己动手写一个ajax异步上传文件的jquery插件

  前不久做了一个文件上传的功能页面,这次开发中我遇到了些问题,开发的时候由于时间比较紧张,因此有些细节做得并不是太仔细,所以最近几天将前面做得东西整理了下,在这里和大家 一起分享下。

  首先我介绍下我所做的功能页面,页面会同时上传两个文件,一个是数据文件,一个是签名文件,而且数据文件一般都是比较大的,上传的同时文件的数据要同步解析同步校验,最终录入到数据库里,这就导致文件上传的时间都比较长,为了得到更好的用户体验,上传文件的时候页面做一个等待的遮罩效果,这个如果用ajax异步提交就能很好的作出效果,但是标准的ajax技术可以异步上传文件吗?答案是不行,至少标准的ajax技术里没有直接用来上传文件的方法,这时同事给了我一个项目组里使用过的ajax上传文件的插件,研究了下很让我失望,这个插件只能上传一个文件同时也不支持遮罩的效果,况且代码也超级烂:作为jQuery插件,代码里面居然很少使用jQuery方法,也不知道当时同事从那里找到了这个插件。

  我现在对每一次能写js代码的机会都坚决把握,这次也不例外,我想自己写个ajax上传的jQuery插件。

  ajax上传文件原理是一种用不可见的form和iframe框架模拟ajax异步提交的方式,我在制作的插件里添加了一个用于上传文件的form和iframe,其中form也是对用户不可见的,但是它是负责文件上传的form,iframe则是接收返回数据的载体,下面我把我页面的源码和页面上传文件时候的代码贴在下面,大家可以比较下:

  源文件ajaxuploadfile.html:

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

<html>

<head>

<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">

<title>Ajax File Upload PHP</title>

</head>

<script type="text/javascript" src="js/jquery-1.7.1.js"></script>

<script type="text/javascript" src="js/jquery.ajaxupload.1.0.js"></script>

<body>

    <form id="aupfFrm" name="aupfFrm" style="position: absolute;top:50px;left: 80px;">

        <label for="username">&nbsp;&nbsp;&nbsp;用户姓名:</label>

        <input type="text" id="username" name="username"/>

        <br/>

        <label for="userpwd">&nbsp;&nbsp;&nbsp;用户密码:</label>

        <input type="password" id="userpwd" name="userpwd"/>

        <br/>

        <label for="uploadFile">请选择文件1:</label></label>

        <input type="file" id="uploadFile1" name="uploadFile1"/>

        <br/>

        <label for="uploadFile">请选择文件2:</label></label>

        <input type="file" id="uploadFile2" name="uploadFile2"/>

        <br/>

        <br/>

        <center>

            <input type="button" id="upBtn" name="upBtn" value="BUTTON"/>

        </center>

    </form>

    <span id="showErrInfo" style="color: red"></span>

</body>

</html>

<script type="text/javascript">

    $(document).ready(function(){

        /*

        $("#upBtn").bind("click",function(){

            $.ajaxFileUpload({

                url:"php/uploadfile.php",

                loadPicUrl:"images/loading.gif",

                formElemIds:["username","userpwd","uploadFile1","uploadFile2"],

                dataType:"html",

                success:function(data){

                    $("body").html(data);

                },

                error:function(data){

                    alert(data);

                }

            });

        });

        */

        $("#upBtn").bind("click",function(){

            $.ajaxFileUpload({

                url:"php/uploadfile.php",

                loadPicUrl:"images/loading.gif",

                formElemIds:["username","userpwd","uploadFile1","uploadFile2"],

                dataType:"json",

                success:function(data){

                    $("#showErrInfo").text("");// 清空原来的提示信息

                    $("#showErrInfo").text("用户姓名:" + data.username + 

                                                ";用户密码:" + data.userpwd + 

                                                        ";请求类型:" + data.dataType + 

                                                            ";提示信息:" + data.retTipInfo);

                },

                error:function(data){

                    alert(data);

                }

            });

        });        

    });

</script>

  上传文件过程中的页面代码:

<form enctype="multipart/form-data" id="jqAjaxUploadFrom1344865748585"

name="jqAjaxUploadFrom1344865748585" method="post" action="php/uploadfile.php"

style="position: absolute; top: -1200px; left: -1200px;" target="jqAjaxUploadIframe1344865748585">

    <input type="text" name="username" id="jqUploadFile1344865748585username">

    <input type="password" name="userpwd" id="jqUploadFile1344865748585userpwd">

    <input type="file" name="uploadFile1" id="jqUploadFile1344865748585uploadFile1">

    <input type="file" name="uploadFile2" id="jqUploadFile1344865748585uploadFile2">

    <input type="hidden" name="dataTp" id="dataTp" value="json">

</form>

<iframe name="jqAjaxUploadIframe1344865748585" id="jqAjaxUploadIframe1344865748585"

style="position: absolute; top: -1000px; left: -1000px;" src="php/uploadfile.php">

</iframe>

<html>

    

    <head>

        <meta content="text/html; charset=UTF-8" http-equiv="Content-Type">

        <title>

            Ajax File Upload PHP

        </title>

        <script src="js/jquery-1.7.1.js" type="text/javascript">

        </script>

        <script src="js/jquery.ajaxupload.1.0.js" type="text/javascript">

        </script>

    </head>

    

    <body>

        <form style="position: absolute;top:50px;left: 80px;" name="aupfFrm" id="aupfFrm">

            <label for="username">

                &nbsp;&nbsp;&nbsp;用户姓名:

            </label>

            <input type="text" name="username" id="username">

            <br>

            <label for="userpwd">

                &nbsp;&nbsp;&nbsp;用户密码:

            </label>

            <input type="password" name="userpwd" id="userpwd">

            <br>

            <label for="uploadFile">

                请选择文件1:

            </label>

            <input type="file" name="uploadFile1" id="uploadFile1">

            <br>

            <label for="uploadFile">

                请选择文件2:

            </label>

            <input type="file" name="uploadFile2" id="uploadFile2">

            <br>

            <br>

            <center>

                <input type="button" value="BUTTON" name="upBtn" id="upBtn">

            </center>

        </form>

        <span style="color: red" id="showErrInfo">

        </span>

        <script type="text/javascript">

            $(document).ready(function() {

                /*

        $("#upBtn").bind("click",function(){

            $.ajaxFileUpload({

                url:"php/uploadfile.php",

                loadPicUrl:"images/loading.gif",

                formElemIds:["username","userpwd","uploadFile1","uploadFile2"],

                dataType:"html",

                success:function(data){

                    $("body").html(data);

                },

                error:function(data){

                    alert(data);

                }

            });

        });

        */

                $("#upBtn").bind("click",

                function() {

                    $.ajaxFileUpload({

                        url: "php/uploadfile.php",

                        loadPicUrl: "images/loading.gif",

                        formElemIds: ["username", "userpwd", "uploadFile1", "uploadFile2"],

                        dataType: "json",

                        success: function(data) {

                            $("#showErrInfo").text(""); // 清空原来的提示信息

                            $("#showErrInfo").text("用户姓名:" + data.username + ";用户密码:" + data.userpwd + ";请求类型:" + data.dataType + ";提示信息:" + data.retTipInfo);

                        },

                        error: function(data) {

                            alert(data);

                        }

                    });

                });

            });

        </script>

        <div id="up_overlay" style="display: block; height: 100%; width: 100%; left: 0px; top: 0px; position: fixed; z-index: 999; background-color: rgb(0, 0, 0); opacity: 0.59;">

        </div>

        <img id="loadimg" style="left: 0px; top: 0px; margin-left: 280px; margin-top: 150px; position: fixed; z-index: 999; display: block;"

        src="images/loading.gif">

        <form enctype="multipart/form-data" id="jqAjaxUploadFrom1344865748585"

        name="jqAjaxUploadFrom1344865748585" method="post" action="php/uploadfile.php"

        style="position: absolute; top: -1200px; left: -1200px;" target="jqAjaxUploadIframe1344865748585">

            <input type="text" name="username" id="jqUploadFile1344865748585username">

            <input type="password" name="userpwd" id="jqUploadFile1344865748585userpwd">

            <input type="file" name="uploadFile1" id="jqUploadFile1344865748585uploadFile1">

            <input type="file" name="uploadFile2" id="jqUploadFile1344865748585uploadFile2">

            <input type="hidden" name="dataTp" id="dataTp" value="json">

        </form>

        <iframe name="jqAjaxUploadIframe1344865748585" id="jqAjaxUploadIframe1344865748585"

        style="position: absolute; top: -1000px; left: -1000px;" src="php/uploadfile.php">

        </iframe>

    </body>



</html>

  其中form代码:

        <form enctype="multipart/form-data" id="jqAjaxUploadFrom1344865748585"

        name="jqAjaxUploadFrom1344865748585" method="post" action="php/uploadfile.php"

        style="position: absolute; top: -1200px; left: -1200px;" target="jqAjaxUploadIframe1344865748585">

            <input type="text" name="username" id="jqUploadFile1344865748585username">

            <input type="password" name="userpwd" id="jqUploadFile1344865748585userpwd">

            <input type="file" name="uploadFile1" id="jqUploadFile1344865748585uploadFile1">

            <input type="file" name="uploadFile2" id="jqUploadFile1344865748585uploadFile2">

            <input type="hidden" name="dataTp" id="dataTp" value="json">

        </form>

  iframe代码:

        <iframe name="jqAjaxUploadIframe1344865748585" id="jqAjaxUploadIframe1344865748585"

        style="position: absolute; top: -1000px; left: -1000px;" src="php/uploadfile.php">

        </iframe>

  遮罩的代码:

        <div id="up_overlay" style="display: block; height: 100%; width: 100%; left: 0px; top: 0px; position: fixed; z-index: 999; background-color: rgb(0, 0, 0); opacity: 0.59;">

        </div>

        <img id="loadimg" style="left: 0px; top: 0px; margin-left: 280px; margin-top: 150px; position: fixed; z-index: 999; display: block;"

        src="images/loading.gif">

  调用方式:

        $("#upBtn").bind("click",function(){

            $.ajaxFileUpload({

                url:"php/uploadfile.php",

                loadPicUrl:"images/loading.gif",

                formElemIds:["username","userpwd","uploadFile1","uploadFile2"],

                dataType:"json",

                success:function(data){

                    $("#showErrInfo").text("");// 清空原来的提示信息

                    $("#showErrInfo").text("用户姓名:" + data.username + 

                                                ";用户密码:" + data.userpwd + 

                                                        ";请求类型:" + data.dataType + 

                                                            ";提示信息:" + data.retTipInfo);

                },

                error:function(data){

                    alert(data);

                }

            });

        });    

  

参数介绍:
url:请求路径;
loadPicUrl:遮罩效果的等待图片;
formElemIds:提交到服务端的form元素的id值,注意一定要是个数组,如果那个字段的id没有写到数组里,那么它的数据也不会提交到服务端;
dataType:指定返回值的数据类型,我计划写html,json,xml和script,现在实现了html和script,其他两种也很简单,以后有空再补充;
success:文件上传成功的回调函数;
error:文件上传失败的回调函数。

 

下面就是我程序的源码了:

首先还是目录结果,如图:

javascript及php笔记:自己动手写一个ajax异步上传文件的jquery插件

javascript代码(jquery.ajaxupload.1.0.js):

View Code
// 制作jQuery插件 author:xiajun  add 2012-08-13 ajax多文件上传

;(function($){

    $.extend({

        createUploadIframe:function(id,url){// 创建用于文件上传的iframe

            var upIframeId = "jqAjaxUploadIframe" + id;

            var jqIfrmObj = $('<iframe id="' + upIframeId + '" name="' + upIframeId + '" />');

            

            // iframe的位置

            jqIfrmObj.css('position','absolute');

            jqIfrmObj.css('top','-1000px');

            jqIfrmObj.css('left','-1000px');

            jqIfrmObj.attr('src',url);

            

            $('body').append(jqIfrmObj);

            return jqIfrmObj;

        },

        createUploadForm:function(timeId,fileElems,dataType){// 创建用于上传文件的form

            var upFormId = "jqAjaxUploadFrom" + timeId;

            var jqFormObj = $('<form  action="" method="POST" name="' + upFormId + '" id="' + upFormId + '" enctype="multipart/form-data"></form>');

            

            for (var i = 0,len = fileElems.length;i < len;i++){

                var fileElemObj = fileElems[i],

                    fileId = 'jqUploadFile' + timeId + fileElemObj,

                    oldElem = $('#' + fileElemObj),

                    newElem = $(oldElem).clone();

                    

                $(oldElem).attr('id',fileId);

                $(oldElem).before(newElem);

                $(oldElem).appendTo(jqFormObj);

            }

            

            // 数据返回类型

            var dataTpIpt = $("<input type='hidden' id='dataTp' name = 'dataTp'/>");

            dataTpIpt.val(dataType);

            jqFormObj.append(dataTpIpt);

            

            $(jqFormObj).css('position', 'absolute');

            $(jqFormObj).css('top', '-1200px');

            $(jqFormObj).css('left', '-1200px');

            $(jqFormObj).appendTo('body');    

            

            return jqFormObj;        

        },

        createOverLay:function(){// 创建遮罩效果 

            var overLayDiv = $("<div></div>");

            overLayDiv.attr("id","up_overlay");

            overLayDiv.css("display","block");

            overLayDiv.css("height","100%");

            overLayDiv.css("width","100%");

            overLayDiv.css("left","0px");

            overLayDiv.css("top","0px");

            overLayDiv.css("position","fixed");

            overLayDiv.css("z-index","999");

            overLayDiv.css("background-color","#000000");

            overLayDiv.css("opacity","0.59");

            overLayDiv.css("filter","Alpha(opacity=50)");

            $("body").append(overLayDiv);

        },

        createLoadingPic:function(loadPicUrl){// 创建正在加载的图片

            var oLoadingPic = $("<img></img>");

            oLoadingPic.attr("id","loadimg");

            oLoadingPic.css("left","0px");

            oLoadingPic.css("top","0px");

            oLoadingPic.css("margin-left","280px");

            oLoadingPic.css("margin-top","150px");

            oLoadingPic.css("position","fixed");

            oLoadingPic.css("z-index","999");

            oLoadingPic.css("display","block");

            

            oLoadingPic.attr("src",loadPicUrl);

            

            $("body").append(oLoadingPic);

        },

        ajaxFileUpload:function(oJson){// 文件上传方法

            // 遮罩效果 start

            jQuery.createOverLay();

            jQuery.createLoadingPic(oJson.loadPicUrl);

            // 遮罩效果 end

            

            // 创建用于上传文件的iframe和form start

            var timeId = new Date().getTime();

            var upfForm = jQuery.createUploadForm(timeId,oJson.formElemIds,oJson.dataType);

                upfIframe = jQuery.createUploadIframe(timeId,oJson.url),

                upfFormId = "jqAjaxUploadFrom" + timeId,

                upfIframeId = "jqAjaxUploadIframe" + timeId;

            // 创建用于上传文件的iframe和form end

                

            // 上传文件的回调函数 start

            var xml = {};

            var uploadFileCallback = function(){

                var cbUpfIfrm = $("#" + upfIframeId);

                try{

                    xml = cbUpfIfrm.contents().find("body");

                    

                    var sErrFlag = $.trim(cbUpfIfrm.contents().find("body").find("input[id='errFlag']").val()),

                        sTipInfo = $.trim(cbUpfIfrm.contents().find("body").find("input[id='errInfo']").val());

                    

                    if (sErrFlag == 'false'){

                        if (oJson.error){

                            oJson.error(sTipInfo);    

                        }

                    }else if (sErrFlag == 'true'){

                        var retData = jQuery.uploadRetHttpData(xml,oJson.dataType);

                        

                        if (oJson.success){

                            $("#up_overlay").remove();

                            $("#loadimg").remove();

                            oJson.success(retData);    

                        }                        

                    }

                    

                    $(cbUpfIfrm).unbind();

                    

                    setTimeout(function(){

                        $(upfIframe).remove();

                        $(upfForm).remove();

                    },100);                    

                            

                    xml = null;        

                }catch(e){

                    alert("Callback error1:" + e);    

                }



            }

            // 上传文件的回调函数 end

            

            try{

                var ajaxUpfForm = $("#" + upfFormId);

                ajaxUpfForm.attr("action",oJson.url);

                ajaxUpfForm.attr("method","post");

                ajaxUpfForm.attr("target",upfIframeId);

                

                if (ajaxUpfForm.attr("encoding")){

                    ajaxUpfForm.attr("encoding","multipart/form-data");

                }else{

                    ajaxUpfForm.attr("enctype","multipart/form-data");    

                }

                

                ajaxUpfForm.submit();

            }catch(e){

                alert("ajaxFileUpload Error:" + e);

            }

            

            $("#" + upfIframeId).bind("load",uploadFileCallback);

            

            return {abort: function () {}};    

        },

        uploadRetHttpData:function(resp,type){// 上传返回的数据

            switch (type) {

                case 'html':

                    return resp.find("div[id='resultData']").html();

                    break;

                case 'xml':

                    alert("to do ....");// 以后再写

                    break;

                case 'json':

                    return eval("(" + resp.find("div[id='resultData']").text() + ")");

                    break;

                case 'script':

                    alert("to do ....");// 以后再写

                    break;

                default:

                    break;

            }

        }

    });

})(jQuery);

  服务端我使用的是php,我的工作语言是java,今天使用php也是第一次尝试另一种服务端语言,这个决定也不是临时的,我打算以后自我学习所写的代码都将会是脚本语言,最近一段时间是php,等php熟练后就是python,我的计划是学会四门脚本语言,另外两种是nodeJs和ruby了。

  使用php写代码的感觉就是爽,比java方便多了,做网站就应该用php这样的脚本语言。

下面是我服务端源码(uploadfile.php):

<?php

    //sleep(234);

    

    /**

     * 上传错误处理函数

     * Enter description here ...

     * @param $errCode

     */

    function parseFileErr($fileNm,$errCode){

        setOperateFlag('false');

        switch ($errCode) {

            case 1:

                echo $fileNm . ":文件大小超过了PHP.ini中的文件限制!";

                break;

            case 2:

                echo $fileNm . ":文件大小超过了浏览器限制!";

                break;

            case 3:

                echo $fileNm . ":文件部分被上传!";

                break;

            case 4:

                echo $fileNm . ":没有找到要上传的文件!";

                break;

            case 5:

                echo $fileNm . ":服务器临时文件夹丢失,请重新上传!";

                break;

            case 6:

                echo $fileNm . ":文件写入到临时文件夹出错!";

                break;            

            default:

                echo $fileNm . ":文件上传错误!!";

                break;

        }

    }

    

    /**

     * 设置操作状态 true表示成功 false 表示失败

     * Enter description here ...

     * @param $flag

     */

    function setOperateFlag($flag,$tipInfo){

        echo "<input type='hidden' id='errFlag' name='errFlag' value='" . $flag . "' />";

        echo "<input type='hidden' id='errInfo' name='errInfo' value='" . $tipInfo . "' />";

    }

    

    /**

     * 校验文件的类型和大小

     * Enter description here ...

     * @param $upFileTp

     * @param $upFileSize

     */

    function checkFileTypeAndSize($upFileTp,$upFileSize){

        if ($upFileSize < 28480){

            return true;

        }else{

            return false;

        }

    }

    

    /**

     * 判断上传文件是否存在

     * Enter description here ...

     * @param $upFileNm

     */

    function checkFileExists($upFileNm){

        if (file_exists($upFileNm)){

            return "tp0_" . $upFileNm;// 已存在文件改名字保存

        }else{

            return $upFileNm;

        }

    }

    

    /**

     * 返回数据

     * Enter description here ...

     */

    function resultDataFtn(){

        $reqUserNm = $_REQUEST["username"];

        $reqUserPwd = $_REQUEST["userpwd"];

        $reqDataTp = $_REQUEST["dataTp"];

        echo "<div id='resultData'>";

        if ($reqDataTp == 'html'){

            echo "<h1 style='color:red'>PHP Ajax 多文件上传 成功</h1>";

        }elseif ($reqDataTp == 'json'){

            $jsonArr = array("username"=> $reqUserNm,

                             "userpwd" => $reqUserPwd,

                             "dataType" => $reqDataTp,

                             "retTipInfo" => "PHP Ajax 多文件上传 成功");

            echo json_encode($jsonArr);

        }

        echo "</div>";

    }

    

    // 上传文件1

    $upFile01Name = $_FILES['uploadFile1']['name'];

    $upFile01Size = $_FILES['uploadFile1']['size'];

    $upFile01TmpNm = $_FILES['uploadFile1']['tmp_name'];

    $upFile01Type = $_FILES['uploadFile1']['type'];

    $upFile01Err = $_FILES['uploadFile1']['error'];

    

    // 上传文件2

    $upFile02Name = $_FILES['uploadFile2']['name'];

    $upFile02Size = $_FILES['uploadFile2']['size'];

    $upFile02TmpNm = $_FILES['uploadFile2']['tmp_name'];

    $upFile02Type = $_FILES['uploadFile2']['type'];    

    $upFile02Err = $_FILES['uploadFile2']['error'];

    

    if ($upFile01Name == '' || $upFile02Name == ''){

        setOperateFlag('false',"请上传文件!");

        //echo "<script>alert('请上传文件!');</script>";

    }else{

        if ($upFile01Err > 0 || $upFile02Err > 0){

            //$upFile01Err > 0 ? parseFileErr($upFile01Name, $upFile01Err) : "";

            //$upFile02Err > 0 ? parseFileErr($upFile02Name, $upFile02Err) : "";

            setOperateFlag('false',"上传失败!");

        }else{

            if (!checkFileTypeAndSize($upFile01Type, $upFile01Size) || !checkFileTypeAndSize($upFile02Type, $upFile02Size)){    

                setOperateFlag('false','上传的文件过大!');

                //echo "<script>alert('上传的文件过大!');</script>";

            }else{

                setOperateFlag('true',"成功");

                move_uploaded_file($upFile01TmpNm, checkFileExists($upFile01Name));

                move_uploaded_file($upFile02TmpNm, checkFileExists($upFile02Name));

                resultDataFtn();// 结果数据处理

            }

        }

    }

?>

  这个插件写的很匆忙,问题肯定很多,特别是服务端和客户端有些逻辑有一定耦合,我估计某些童鞋想把插件迁移到其他的服务端上会有点麻烦,等有时间我会进一步改进自己的代码。

 

  源代码下载路径:
  http://files.cnblogs.com/sharpxiajun/ajaxfileupload1.0.zip

 

 

 

 

 

 

 

 

你可能感兴趣的:(JavaScript)