Modal框通过ajaxform上传文件及各种ajax使用方法,初试牛刀

来源:互联网 发布:ui需要编程吗 编辑:程序博客网 时间:2024/06/05 18:14

    第一次写博客,欢迎指点。

    开发环境和开发工具是:apache,mysql,php,使用thinkphp框架,和bootstrap前段框架,讲的主要是前段的html和js,jquery相关,然而我是初学阶段,请多包涵。

    公司要求开发一个后台管理系统,包括的无非就是增删改查操作,目前大部分逻辑简单的功能已经实现,剩下一个添加计划的功能。

    这个添加计划功能要求:

          ① 每个计划分为不同的天数,天数不固定;

          ② 每天分为几个不同的步骤,步骤不固定;

    主要是以上两点,难点在不固定性,和前端每步一传值得设计上。

    因为计划每步都包含图片和视频,而传递大文件和较多文件时,服务器有时会发生超时或者其他一些不可预见的错误,因此我这里不采用集中填写数据,通过hide(),show()方法来更改当前输入栏或用html()方法生成输入栏的方式解决这个问题。

    想要达到一步一传值的目的,大概最普遍的就是ajax了,那么好了,引入jquery.js,bootstrap.js,bootstrap.css文件,使用bootstrap的原因是我们需要使用到模态框(Modal)。

    想给大家看下我的前段吧!

这个是点击添加之后的modal,如图可以看到需要添加各种数据和两张图片,上方数据用$.ajax()可以直接传递到后台存储,关键是图片怎么办?

    上传图片时,我们的方法都是通过读取$_FILES里的name和其他一些参数,使用框架的upload类进行文件的上传工作,那么也就是说,我们只要访问到了upload类就能实现上传了吧?

    做一个测试吧,实践是检验真理的唯一标准。

                    首先我做一个form表单:

 <form id="form" action="../manage/uploadphoto" enctype="multipart/form-data">                  <div class="upday" style="width:49%;height:200px;border-radius: 5px;border:1px solid #ccc;margin-top:5px;float: left">                    <input type="text" size="20" name="upfile1" id="upfile1" style="display: none">                      <input type="button" value="选择图片" onclick="path1.click()" style="border:1px solid #ccc;background:#fff;color: #131313">                      <input type="file" id="path1" style="display:none" onchange="upfile1.value=this.value">                      <p style="margin-left: 46px;margin-top: -30px;color:#999">请上传尺寸为750*426px的图片</p>                  </div>                  <div class="upday" style="width:49%;height:200px;border-radius: 5px;border:1px solid #ccc;margin-top:5px;float: left;margin-left: 5px">                    <div class="upfile">                      <input type="text" size="20" name="upfile2" id="upfile2" style="display: none">                        <input type="button" value="选择图片" onclick="path2.click()" style="border:1px solid #ccc;background:#fff;color: #131313">                        <input type="file" id="path2" style="display:none" onchange="upfile2.value=this.value">                    </div>                      <p style="margin-left: 46px;margin-top: -30px;;color:#999">请上传尺寸为750*260px的图片</p>                  </div>                  </form>

              以上是我的源代码了,有点CSS在里边请见谅!

              可以看到我把图片放在了一个form表单中,通过表单的提交来调用manage控制器的uploadphoto方法,然后来看看uploadphoto方法,这里我直接用的thinkphp的upload类

public function uploadphoto(){                $upload = new \Think\Upload();// 实例化上传类                $upload->maxSize   =     $_FILES['upfile1']['size'] ;// 设置附件>上传大小                $upload->exts      =     array('jpg', 'gif', 'png', 'jpeg');// >设置附件上传类型                $upload->saveName  =  '';                $upload->rootPath  =      'D:\php\phpstudy\WWW\APP\Style\imgs\test'; // 设置附件上传根目录                $upload->savePath  =      ''; // 设置附件上传(子)目录                // 上传文件                 $info   =   $upload->upload();                if(!$info) {// 上传错误提示错误信息                    $a = $upload->getError();                                   }else{// 上传成功 获取上传文件信息                    foreach($info as $file){                        $a =  $file['savepath'].$file['savename'];                    }                        return $a;                }          }

   看到我们取得是名为upfile1的文件,现在我们通过提交form表单来试验看看,文件能否提交到test文件夹中。

  function sub(){    $("#form").submit();  }

    这是JS提交表单的代码。

看到代码显示提交成功,然而并没有文件出现在test中。

      那我们来看看,到底有没有文件被上传。

      在uploadphoto方法中加入:

    echo "<pre>";
    var_dump($_FILES);
    echo "</pre>";
    exit;


接下来再看数据;

并没有上传的文件,这很不应该,说明从头就开始是错的,我们从头看,改用最基本的input[type=file]:

 <input type="file" name="upfile1">

保存,重试。返回结果同上,错误,那么错误可能不在这里。

我们用最普通最简单地方法做一次,在form中加上:

 <input type="submit" name="tijiao ">

这下总不会错了吧?

还是错?!你这有毒啊!

哦,好吧,我发现我用的是默认的get方法,趁你们没发现我赶紧加上method="post",重新试一次,至少有上传文件显示了!

删掉我们加的提交按钮后,继续测试。

好啦,又跪啦,网上找到美化上传框的html有问题,先换成普通的测一下再说!

至少我们的jquery提交语句是有效的!

我们看下网上的这段html代码:

                    <input type="text" size="20" name="upfile1" id="upfile1" style="display: none"> 
                    <input type="button" value="选择图片" onclick="path1.click()" style="border:1px solid #ccc;background:#fff;color: #131313"> 
                    <input type="file" id="path1" style="display:none" onchange="upfile1.value=this.value">

第三句的onchange属性,是当input内容改变时将值赋给第一句,然后第一句本来是显示出来的你的上传文件的本地地址,后来因为用不上就给我删了,此处可以把它注释掉了,然而我们把它注释掉之前,要看看它内部有没有有用的东西,这里就看name和id属性,咦?我们的name不是应该在file里?赶紧挪过去,并把onchange删掉,第二句是给我们看的,点击做这个button相当于点击了file,一个click监听器。

        好了,第一次修改完成,保存,测试!

        嗯!好顺利的OK啦!有了上传文件接下来就是服务器端上传类的活了。把调试代码注释掉,完整测试。

        没传过去,感觉是upload类的问题,找到upload类,在构造函数中加上:

                      echo "success";

        然后实例化upload():

                      $upload = new \Think\Upload();// 实例化上传类    

        下边的步骤先不执行,exit;

         输出了success,构造成功,这个好像多此一举了,毕竟构造函数一点会执行。

                   $a = $upload->getError();
                    var_dump($a);
                    exit;

          这里可以输出上传类的错误信息,先看看;

          添加几个标志位后,发现,我的上传居然成功了....但是你传哪去了?

          $upload->rootPath  =      'D:\php\phpstudy\WWW\APP\Style\imgs\test/'; // 设置附件上传根目录

          最后的"/"漏掉了。。。补上后,发现,成功了呢!

          因为我的类被我改过,所以名字和后缀和大家的不一样,但是肯定也能成功的

            就酱,我们回头把测试的东西都删掉。


          现在是这样了:

<form id="form" action="../manage/uploadphoto" method="post" enctype="multipart/form-data">                  <div class="upday" style="width:49%;height:200px;border-radius: 5px;border:1px solid #ccc;margin-top:5px;float: left">                    <!-- <input type="text" size="20"  id="upfile1" style="display: none">   -->                    <input type="button" value="选择图片" onclick="path1.click()" style="border:1px solid #ccc;background:#fff;color: #131313">                      <input type="file" id="path1" name="upfile1" style="display:none">                      <p style="margin-left: 46px;margin-top: -30px;color:#999">请上传尺寸为750*426px的图片</p>                  </div>                  <div class="upday" style="width:49%;height:200px;border-radius: 5px;border:1px solid #ccc;margin-top:5px;float: left;margin-left: 5px">                    <div class="upfile">                      <input type="button" value="选择图片" onclick="path2.click()" style="border:1px solid #ccc;background:#fff;color: #131313">                        <input type="file" id="path2" name="upfile2" style="display:none">                    </div>                      <p style="margin-left: 46px;margin-top: -30px;;color:#999">请上传尺寸为750*260px的图片</p>                  </div>                  </form>


            然后要说的:我们有两个file框啊!第二个呢?

            第二个很简单,我冷冷说道;

            打开我们的manage控制器,在方法uploadphoto中,调用同控制器下的另一个方法,uploadphoto2(),对,和这个方法的内容一样,拷贝黏贴,改下方法名,$_FILES的名字改为upfile2,存储地址改为test2文件夹。在uploadphoto中加:

                          $this->uploadphoto2();

            其实这个uploadphoto方法在服务器上已经被我做成了函数,不用这么麻烦的调用,有机会以后说吧。

            现在这些我们已经改好了,开始测试!

            只上传成功了一个,想想不能这样做,把uploadphoto方法名改成uploadphoto1(),然后重新定义uploadphoto():

 

 public function uploadphoto(){    $this->uploadphoto1();    $this->uploadphoto2();    }


             再试一次啦,试之前把文件夹里的文件清一下。

             你们怎么就都跑test文件里了呢?

             我的猜想是,这个upload类并不区分上传文件的name,而是一股脑全部传到一个文件夹中,所以都出现在了第一个文件夹里,而第二个文件夹里没有文件,我们掉个个,看看。

 public function uploadphoto(){    $this->uploadphoto2();    $this->uploadphoto1();    }


            所以我是正确哒,接下来想办法给他们分开。

            讲道理不应该这样,可能是我把类改了的缘故,找一个新的类试试

            还是不行......

            查了下upload文档

            可能是我的name设置出了点问题,改!

            两个文件name区别开,现在继续;

            怎么还是传一个文件夹里了...我记得以前不是这样的,可能是windows和linux系统不同吧,在Linux下用同样的方法我实现了向不同文件夹传文件的功能。

            那么,我们换一种思路,大概构想是,给上传的文件加上特殊标识,从而判断他应该存入哪个文件夹。

            我坚持认为这是操作系统的问题。留待日后解决。


            功能算是实现了吧,特地准备的jquery.form.js也没用上。

            这还不算完,你得把图片名存到数据库才行啊,这里因为就一张图,所以我们就用简单的add()来存就可以了。

            实例化数据库表的model,然后add他。

            add()的返回值是这条记录的ID号,因为是新增的记录,所以我们需要ID号来知道我们到底做到了哪里,这个id需要返回。未来我们会用ajax来访问这个上传文件的接口,所以此处我们用 ajaxReturn来返回数据,代码如下:

    public function uploadphoto(){    $map['plan_imgs'] = $_FILES['upfilebig']['name'];    $map['plan_imgs_small'] = $_FILES['upfilesmall']['name'];    $model = M('plan_skin');    $id = $model -> save($map);    $this->uploadphoto2();    $this->uploadphoto1();    if($id){    $this->ajaxReturn(array('id'=>$id,'s'=>true));    }else{    $this->ajaxReturn(array('s'=>false));    }    }


              现在来实现ajax操作,获取ID,这个ID非常重要。

              既然决定了先上传图片来获取ID,那么必须保证上传的优先性。

              这时候显然。submit()已经无法满足我们了,需要使用jquery.form.js,辛辛苦苦下的,不用怎么行!

              引入文件后,代码如下:

$(document).ready(function(){    $("#next").click(function(){                $("#form").ajaxSubmit({                    type:'post',                    url:'../manage/uploadphoto',                    success:function(data){                        alert(data);                    },                    error:function(XmlHttpRequest,textStatus,errorThrown){                        console.log(XmlHttpRequest);                        console.log(textStatus);                        console.log(errorThrown);                    }                });            });    });


            注释掉#next的onclick事件,然后改成如上代码,点击下一步,弹出一个空白警告框,去文件夹一看,咦,真的有!

            用这个插件就可以完美解决前一个问题啦,不就是两个表单吗,能解决问题就行啦!

            那么,我们要接收他的返回值了,这是一个叫ID的重要人士。

            返回给我false,我才想起来,我漏建了一个字段,赶紧去补上。


          成功返回id啦。

          现在我们不要他alert出来,我们把他赋值给我在html中留的input[type=hidden]里去。

  <input type="hidden" name="id" id="id" value=""><!--隐藏框保存id值,保证正确存放数据-->  <input type="hidden" name="index_day" id="index_day" value=""><!--隐藏标志位,记录进行的天数-->  <input type="hidden" id="index_step" name="index_step" value=""><!--隐藏标志位,记录进行的步骤数-->


          方法简单粗暴:

                  success:function(data){
                        $("#id").val(data['id']);
                    },

          用这种方法主要是因为js没有全局变量什么的,也是没有办法的办法。

          有了这个ID,之后的是就好做了,你还要post其他数据到后台是吧?好,success里调用这个post_plan()方法,加上你们

          成这样:

  $(document).ready(function(){    $("#next").click(function(){                $("#form").ajaxSubmit({                    type:'post',                    url:'../manage/uploadphoto',                    success:function(data){                        $("#id").val(data['id']);                        post_plan();                    },                    error:function(XmlHttpRequest,textStatus,errorThrown){                        console.log(XmlHttpRequest);                        console.log(textStatus);                        console.log(errorThrown);                    }                });            });    });

       

post_plan():

  function post_plan(){    var skin_val = get_radio_checked("skin");    var class_val = get_radio_checked("class");    $.ajax({      url:"../manage/swb_add_plan",      data:{'id':$("#id").val(),'plan_title':$("#title").val(),'plan_intr':$("#intr").html(),'plan_skin':skin_val,'plan_class':class_val,'plan_days':$("#days").val(),'plan_daytime':$("#daytime").val(),'plan_time':$('#time').val(),'plan_num':$("#num").val(),'plan_step_num':$("#step_num").val()},      type:'post',      success:function(d){        alert('已发送');      }    })  }

              其中,get_radio_checked()是一个获取radio被选元素值得方法,分享给大家:


    

  //获取radio被选中的值  function get_radio_checked(name){    var radionum = document.getElementsByName(name);    for(var i=0;i<radionum.length;i++){      if(radionum[i].checked){        return radionum[i].value;      }    }  }



          因为后台的接收的接口还没写,所以先观察到发送过去就好了,测试:

    成功!


          然后是后台,swb_add_plan()方法的实现:

 

public function swb_add_plan(){$map['id'] = I("post.id");$map['title'] = I("title");$map['pintr'] = I("pintr");$map['plkin'] = I("pskin");$map['pclass'] = I("pclass");$map['pdays'] = I("pdays");$map['pdaytime'] = I("pdaytime");$map['ptime'] = I("ptime");$map['pnum'] = I("pnum");$map['pstep_num'] = I("pstep_num");$model = M('plan');$res = $model -> save($map);if($res){$this->ajaxReturn(array('s'=>true));}else{$this->ajaxReturn(array('s'=>false));}}


          OK,没问题。

          至此,第一步骤完成了,也算是最简单的一步吧,后续会陆续推出,请关注我~~~

1 0