简单介绍下,这个东西支持ie8及以上高级浏览器。是基于jquery的纯js上传插件,不是坑爹的flash插件。
引入css文件:
<link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css"> 这个你可以不引入,上传功能也是正常的,不过样式就很坑了。 <link rel="stylesheet" href="css/jquery.fileupload.css">这个你也可以不引入,如果你够个性的话。
引入js文件:
<script src="js/jquery-1.9.0.js"></script>这个在例子里面用的是google的链接,被墙了你懂的,所以只能用本地。 <script src="js/vendor/jquery.ui.widget.js"></script>这个顾名思义,ui用的,不影响上传功能。但你还是得引入。 <script src="js/jquery.iframe-transport.js"></script>这个是比如得要的,你要知道,这个上传插件是以这个为基础的。 <script src="js/jquery.fileupload.js"></script>自不必说,这是库。 <script src="js/jquery.fileupload-process.js"></script>你可以不引入,但是我告诉你,处理过程的信息是来自于它的。 <script src="js/jquery.fileupload-validate.js"></script>你可以不引入,但是校验功能是这货做的。
建立被挂载的标签:
页面内添加个file标签:
<input id="fileupload" type="file" name="files[2]" single>
我钟情单文件上传,多文件怎么改?就是把single改了。
你看到了,name=file[2] 这么奇葩的名称,什么意思?因为后面的服务端,需要获取前端标签的名称,一旦你有多个上传的需求,那么就要很多个标签,那么服务端怎么办?它是没办法区分的……,所以唯一的办法,就是把大家都写成一个名字,反正上传是一个一个来的,怕什么呢。其实后端的设置里你能看到,名字是省略后面的下标的。
重头戏来了,实例化上传组件:
<script> /*jslint unparam: true */ /*global window, $ */ $(function () { 'use strict';//使用严格的语法规则 $('#fileupload').fileupload({ inputid:'fileupload',//我要实例化哪个标签 url: 'server/php/',//服务端的地址 dataType: 'json',//数据格式,ajax你懂的 acceptFileTypes: /(\.|\/)(apk|app|rar|zip|7z|tar)$/i,//可上传的文件扩展名 autoUpload: true,//是否选了文件就直接自动上传 maxNumberOfFiles:1,//最多同时上传几个文件 maxChunkSize:10000,//最大接收文件大小 done: function (e, data) {//上传完了干嘛 $.each(data.result.files, function (index, file) { $('#'+data.inputid).prev('span').text('重新上传'); $('#'+data.inputid).attr('value',file.url); }); }, progressall: function (e, data) {//上传过程中,隔段时间就会调起的回调函数,这个东西,主要是用来返回进度的,你看里面的引用,没错,它带回来的参数值,只有total、loaded这种数字。 var progress = parseInt(data.loaded / data.total * 100, 10); $('#progress_'+$(this).fileupload('option', 'inputid')+' .progress-bar').css( 'width', progress + '%' ).next('.progress-text').children('.progress-percent-text').text('上传进度:'+progress + '%'); }, processalways:function (e, data) {//这货是干嘛的呢?就是上传之前调起的函数。没错,如果你选择了自动上传,那么当你点选完了文件,这个货就会被调起。 $('#progress_'+$(this).fileupload('option', 'inputid')+' .progress-bar').css( 'width', '0' ).next('.progress-text').children('.progress-filename-text').empty().next('.progress-percent-text').empty(); $('#'+$(this).fileupload('option', 'inputid')).attr('value','').prev('span').text('上传文件'); var index = data.index, file = data.files[index]; var file_name=file.name.length > 8? file.name.substr(0, 3) + "..." + file.name.substr(file.name.length-5, 5) : file.name; $('#progress_'+$(this).fileupload('option', 'inputid')+' .progress-text .progress-filename-text').text(file_name); if (file.error) { $('#error_'+$(this).fileupload('option', 'inputid')).children('p').text(file.error).css('color','#f60941'); } } }).prop('disabled', !$.support.fileInput) .parent().addClass($.support.fileInput ? undefined : 'disabled');//不用猜了,就是看看是不是支持jqueryajax上传方式。就是上面说的那个frame东东。 }); </script>
//大多数需要关注的内容都集中在这 function __construct($options = null, $initialize = true, $error_messages = null) { $this->response = array(); $this->options = array( 'script_url' => $this->get_full_url().'/',//就是说,我在哪。。。(服务端脚本路径) 'upload_dir' => dirname($this->get_server_var('SCRIPT_FILENAME')).'/files/',//上传到那个路径去 'upload_url' => $this->get_full_url().'/files/',//上传完了得返回吧?告诉js传上去的文件的地址吧,这个就是了 'user_dirs' => false, 'mkdir_mode' => 0755,//linux unix会用到,就是创建的文件的读写权限 'param_name' => 'files',//这货就是前段那个被实例化的file标签的name // Set the following option to 'POST', if your server does not support // DELETE requests. This is a parameter sent to the client: 'delete_type' => 'DELETE',//当我们决定删除某个上传的文件的时候,我们得选择一个ajax方式来提交,那么这个ajax的type就是设置的这个DELETE 'access_control_allow_origin' => '*', 'access_control_allow_credentials' => false, 'access_control_allow_methods' => array(//也就是说,我php服务端到底支持什么ajax方法 'OPTIONS', 'HEAD', 'GET', 'POST', 'PUT', 'PATCH', 'DELETE' ),
修改上传文件的重名规则:当我们两次上传同一个文件的时候,服务器端的命名规则是,使用原本的文件名+(编号)。这个东西有个空格,会导致部分linux命令失效(当然我是说针对这个文件的操作命令)。
原本的命名规则:
protected function upcount_name_callback($matches) { $index = isset($matches[1]) ? ((int)$matches[1]) + 1 : 1; $ext = isset($matches[2]) ? $matches[2] : ''; return ' ('.$index.')'.$ext; } protected function upcount_name($name) { return preg_replace_callback( '/(?:(?: \(([\d]+)\))?(\.[^.]+))?$/', array($this, 'upcount_name_callback'), $name, 1 ); }
改成:
protected function upcount_name_callback($matches) { $index = isset($matches[1]) ? ((int)$matches[1]) + 1 : 1; $ext = isset($matches[2]) ? $matches[2] : ''; return '_'.$index.$ext; } protected function upcount_name($name) { return preg_replace_callback( '/(?:(?:_([\d]+))?(\.[^.]+))?$/', array($this, 'upcount_name_callback'), $name, 1 ); }
其实就是改了个正则表达式……