zoukankan      html  css  js  c++  java
  • 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%;  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%;  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代码(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();// 结果数据处理
                }
            }
        }
    ?>

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

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

  • 相关阅读:
    Codeforces Round #604 (Div. 2) E. Beautiful Mirrors 题解 组合数学
    洛谷P1002 过河卒 题解 动态规划
    python 查看数据类型
    python 输出小技巧
    python 基础定义变量
    python 关键字
    flask restful 反查询
    Please edit configuration/connection/logging settings in '/home/mac126/Desktop/13/test3-1/migrations/alembic.ini' before proceeding.
    KeyError: 'migrate'错误解决办法
    flask 的简单拆分升级版2
  • 原文地址:https://www.cnblogs.com/sharpxiajun/p/2637154.html
Copyright © 2011-2022 走看看