在这个特效横幅的web时代,作为phper也需要跟得上潮流。于是乎,着手研究无刷新上传+无刷新发布日志。 对于无刷新提交文字之类,jquery都已经提供了很好的功能。只需要.get / .post 就可以快速建立一个无刷新提交表单了。但是在文件上传方面,jquery明显遇到
在这个特效横幅的web时代,作为phper也需要跟得上潮流。于是乎,着手研究无刷新上传+无刷新发布日志。
对于无刷新提交文字之类,jquery都已经提供了很好的功能。只需要.get / .post 就可以快速建立一个无刷新提交表单了。但是在文件上传方面,jquery明显遇到难题了(HTML5加强了上传文件功能)。网上有使用iframe这种伪ajax上传文件方式,本文就不在这里讨论了。感兴趣的,可以到开源中国查找。
本文也不讲解thinkphp的无刷新提交日志(不懂的去看官网的示例代码)。主要在无刷新上传 + 无刷新发布日志 整合上。下面的全程讲解,都围绕thinkphp框架为主,原生PHP实现方式也相差不大。
网上比较流行的无刷新上传组建有:swfupload 和uploadify 。我是用uploadify的。
模板代码 index.html:
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <title>UploadiFive Test</title> <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js" type="text/javascript"></script> <script src="http://redich.com/03/__ROOT__/test/js/jquery.uploadify.min.js" type="text/javascript"></script> <script type="text/javascript" src="http://redich.com/03/__ROOT__/test/js/jquery.form.js"></script> <script> $(function(){ $('#from').ajaxForm({ success: complete, dataType: 'json' }); function complete(data){ if (data.status==1){ $('#result').html(data.info).show(); $('#error').hide(); }else{ $('#error').html(data.info).show(); $('#result').hide(); } } }); </script> <link rel="stylesheet" type="text/css" href="http://redich.com/03/__ROOT__/test/js/uploadify.css"> <style type="text/css"> body { font: 13px Arial, Helvetica, Sans-serif; } </style> <div id="warp"> <h1>上传文件和发表文章AJAX示例</h1> <div id="reload"><a href="http://redich.com/03/__URL__/reload">重新提交文章</a></div> <div id="result" style="display:none;"></div> <div id="error" style="display:none;"></div> <form id="from" action="__URL__/add" method="post"> <p><label for="title">标题</label></p> <p><input type="text" name="title"></p> <p><label for="author">作者名称</label></p> <p><input type="text" name="author"></p> <p><label for="content">内容</label></p> <p><textarea name="content" rows="15"></textarea></p> <div id="queue"></div> <p><input id="file_upload" name="file_upload" type="file" multiple></p> <div id="uploadsuccess" style="display:none;"></div> <p><a href="javascript:%24('#file_upload').uploadify('upload')">上传</a> <a href="javascript:%24('#file_upload').uploadify('cancel','*')">重置上传队列</a> </p> <p><input type="submit" value="发表" id="submit"></p> </form> <script type="text/javascript"> var img_id_upload=new Array();//初始化数组,存储已经上传的图片名 var i=0;//初始化数组下标 $(function() { $('#file_upload').uploadify({ 'swf' : '__ROOT__/test/js/uploadify.swf', 'uploader' : '__URL__/upload', 'auto' : false,//关闭自动上传 'multi' : false,//允许同时上传多张图 'buttonText' : '请选择图片',//设置按钮文本片 'queueSizeLimit' : 1,//上传队列最多显示多少个 'onUploadSuccess' : function(file, data, response) { $('#uploadsuccess').html(data).show(); } }); }); </script> </div>
Action部分代码 IndexAction.php
<?php class IndexAction extends Action { public function index(){ $this->display(); } /* * *上传文件 * */ public function upload(){ import("ORG.Net.UploadFile"); $upload = new UploadFile(); $upload->maxSize = 10485760 ; $upload->allowExts = array('jpg', 'gif', 'png', 'jpeg'); $upload->savePath = 'test/'; if(!$upload->upload()) { echo $upload->getErrorMsg(); exit; }else{ //删除旧文件 if(session('?savename')){ if(file_exists('test/'.session('savename'))){ unlink('test/'.session('savename')); session('savename',NULL);//清除session记录 } } $info = $upload->getUploadFileInfo(); session('savename',$info[0]['savename']); } echo '文件"'.$info[0]['name'].'"上传成功!<br>重新上传将删除刚才上传的文件。'; } /* * *提交文章 * */ public function add(){ //防止重复提交 if(!session('?insid')){ $test['title'] = $this->input('title','请输入标题'); $test['author'] = $this->input('author','请输入作者名称'); $test['content'] = $this->input('content','请输入内容'); if(!session('?savename')){ $this->error('请选择上传的文件!'); } $test['filename'] = session('savename'); $sql = M('test'); $result = $sql->add($test); if($result !== false){ $last_id = $sql->getLastInsID(); session('insid',$last_id);//设置一个防重复提交的session insid session('savename',NULL);//释放上传文件的session $this->success('文章发表成功!'); }else{ $this->error('文章发表失败,请重新提交'); } }else{ $this->error('请勿重复提交!'); } } /* * *重新提交文章 * */ public function reload(){ if(session('?savename')){//检查用户是否上传了文件。然后点击了重新提交文章。 if(file_exists('test/'.session('savename'))){ unlink('test/'.session('savename')); session('savename',NULL); } }else{ session('savename',NULL);//释放上传文件的session } session('insid',NULL); redirect(__APP__);//重定向 } public function input($name,$erroinfo){ $name = $this->_POST($name,'trim,htmlspecialchars,strip_tags'); if(empty($name)){ $this->error($erroinfo); return ; } return $name; } }
说一下思路:
首先,通常用户是填写好内容后,选择好上传文件后,提交表单到服务后端,后端进行结果返回。因为用到无刷新上传,所以上传会成为第一个提交到后端处理的。
于是,我想到用session来作一个记录。虽然可以通过返回的结果放到隐藏input表单或者隐藏iframe里面,但是这样的做法很不安全。要是用户对表单的内容进行修改了,那么就会记录错误的文件了。在上述代码中,可以看到我有多次验证上传文件的session是否有设置。有则删除旧文件,再释放出来。
接着因为用到ajax提交表单内容,为了避免用户重复点击提交按钮,导致文章重复写入数据库。我使用了一个session来防止用户重复提交。尽管可以用js来讲按钮失效。但是这样的做法是极度不安全的。
最后,当用户再次点击重新提交文章后。会再次对上传文件的session检查一次。因为可能会存在这样的情况:用户提交了上传文件,但是没有点击提交按钮。这样就上传了一个没用文件到服务器了。检查完毕,再释放防止重复写入的session值。这里有一个BUG:就是要是用户直接关闭浏览器,那么文件就无法删除了= =||。这个各位就自己研究方案吧(给点提示:可以做一个判断,用户离开浏览器后,进行文件删除。因为只有上传成功后,上传文件session才是被释放的)。
文章尾部,我有一点疑问:uploadify为什么定义了错误信息后,还是会弹出英文错误的?难道只能直接改源码部分吗?如果你知道如何解决,请帖出代码指点一下我吧。谢过了
演示地址:http://redich.com/paoyapao/test/
下载地址:http://adf.ly/KYOH0
原文地址:thinkphp无刷新上传+无刷新发布日志, 感谢原作者分享。