当CodeIgniter框架遇到Web Uploader上传组件

代码脚本   1125阅读

在开发后台添加内容页面的时候,有一个字段是保存图片路径,而图片需要由本地上传到服务器,然后由服务器返回图片的远程路径,而且上传图片最好是页面无刷新的。页面无刷新现在已经很容易通过ajax来实现。但是如何通过ajax把文件上传到远程服务器上去呢,这就是一个问题了,本文给出了一个完整的方案。

首先要介绍一些CodeIgniter框架和Web Uploader上传组件

CodeIgniter 是一个小巧但功能强大的 PHP 框架,作为一个简单而“优雅”的工具包,它可以为开发者们建立功能完善的 Web 应用程序。在上一篇文章中已经进行过介绍。

WebUploader是由Baidu WebFE(FEX)团队开发的一个简单的以HTML5为主,FLASH为辅的现代文件上传组件。在现代的浏览器里面能充分发挥HTML5的优势,同时又不摒弃主流IE浏览器,沿用原来的FLASH运行时,兼容IE6+,iOS 6+, android 4+。两套运行时,同样的调用方式,可供用户任意选用。采用大文件分片并发上传,极大的提高了文件上传效率。

下面来介绍实现完整方案的过程。

1、在展现页面中做引入webuploader的css文件

<link rel="stylesheet" type="text/css" href="<?php echo base_url();?>webuploader/webuploader.css">


2、增加文件上传表单的html代码

        <div class="form-group">
            <label for="proj" class="col-sm-3 control-label">项目文件:</label>
            <div class="col-sm-9">
            <div id="uploader">
                <div id="fileList" class="uploader-list"></div>
                <div id="filePicker">选择图片</div>
                <button id="btn-star" class="btn btn-default btn-uploadstar radius ml-10">开始上传</button>
                <input name="uploads" id="uploads" value="" class="sr-only" type="text">
            </div>                
                <?php // echo form_upload(array('type'=>'file','name'=>'proj','id'=>'proj'));?>
            </div>
        </div>

3、在</body>标签前加入javascript的脚本

<script type="text/javascript" src="<?php echo base_url();?>bootstrap/js/jquery.min.js"></script>
<script type="text/javascript" src="<?php echo base_url();?>webuploader/webuploader.js"></script>
<script>
 $list = $("#fileList"),
 $btn = $("#btn-star"),
 state = "pending",
 uploader;

 var uploader = WebUploader.create({
  auto: false,
  swf: '<?php echo base_url();?>webuploader/Uploader.swf',
 
  // 文件接收服务端。
  server: '<?php echo base_url();?>page_admin/webuploader',
 
  // 选择文件的按钮。可选。
  // 内部根据当前运行是创建,可能是input元素,也可能是flash.
                pick: {
                id: '#filePicker',
                innerHTML: '点击选择文件',
                multiple:false
                },
 
  // 不压缩image, 默认如果是jpeg,文件上传前会压缩一把再上传!
  resize: false,
  // 只允许选择图片文件。
  accept: {
   title: 'file',
   extensions: 'jpg,png,pdf,ppt,docx,doc',
   mimeTypes: 'image/*,application/*'
  }
 });
 uploader.on( 'fileQueued', function( file ) {
  var $li = $(
   '<div id="' + file.id + '" class="item">' +
    '<div class="pic-box"><img></div>'+
    '<div class="info">' + file.name + '</div>' +
    '<p class="state">等待上传...</p>'+
   '</div>'
  ),
  $img = $li.find('img');
  $list.append( $li );
 
  // 创建缩略图
  // 如果为非图片文件,可以不用调用此方法。
  // thumbnailWidth x thumbnailHeight 为 100 x 100
                var thumbnailWidth = 100;
                var thumbnailHeight = 100;
  uploader.makeThumb( file, function( error, src ) {
   if ( error ) {
    $img.replaceWith('<span>不能预览</span>');
    return;
   }
 
   $img.attr( 'src', src );
  }, thumbnailWidth, thumbnailHeight );
 });
 // 文件上传过程中创建进度条实时显示。
 uploader.on( 'uploadProgress', function( file, percentage ) {
  var $li = $( '#'+file.id ),
   $percent = $li.find('.progress-box .sr-only');
 
  // 避免重复创建
  if ( !$percent.length ) {
   $percent = $('<div class="progress-box"><span class="progress-bar radius"><span class="sr-only" style="width:0%"></span></span></div>').appendTo( $li ).find('.sr-only');
  }
  $li.find(".state").text("上传中");
  $percent.css( 'width', percentage * 100 + '%' );
 });
 
 // 文件上传成功,给item添加成功class, 用样式标记上传成功。
 uploader.on( 'uploadSuccess', function( file,rep) {
                var response = eval(rep);
                if(response.code === 201)
                {
                    $( '#'+file.id ).addClass('upload-state-success').find(".state").text("已上传");
                    $('#uploads').val(response.message);
                }else
                {
                    $( '#'+file.id ).addClass('upload-state-error').find(".state").text(response.message);
                }
  
 });
 
 // 文件上传失败,显示上传出错。
 uploader.on( 'uploadError', function( file ) {
  $( '#'+file.id ).addClass('upload-state-error').find(".state").text("上传出错");
 });
 
 // 完成上传完了,成功或者失败,先删除进度条。
 uploader.on( 'uploadComplete', function( file ) {
  $( '#'+file.id ).find('.progress-box').fadeOut();
 });
 uploader.on('all', function (type) {
        if (type === 'startUpload') {
            state = 'uploading';
        } else if (type === 'stopUpload') {
            state = 'paused';
        } else if (type === 'uploadFinished') {
            state = 'done';
        }

        if (state === 'uploading') {
            $btn.text('暂停上传');
        } else {
            $btn.text('开始上传');
        }
    });

    $btn.on('click', function () {
        if (state === 'uploading') {
            uploader.stop();
        } else {
            uploader.upload();
        }
        return false;
    });
</script>

这里对其中的代码做一下解释,jquery.min.js和webuploader.js是必须要引入的

server: '<?php echo base_url();?>page_admin/webuploader' 是文件上传的接口。

// 文件上传成功,给item添加成功class, 用样式标记上传成功。
 uploader.on( 'uploadSuccess', function( file,rep) {
                var response = eval(rep);
                if(response.code === 201)
                {
                    $( '#'+file.id ).addClass('upload-state-success').find(".state").text("已上传");
                    $('#uploads').val(response.message);
                }else
                {
                    $( '#'+file.id ).addClass('upload-state-error').find(".state").text(response.message);
                }
  
 });

这段代码是对webuploader的成功上传事件的处理,在测试的时候发现有一个bug是这样的,webuploader配置了可以上传的文件后缀名,比如.jpg,意思是说webuploader限制只能上传jpg的图片;而CodeIgniter的upload类也可以设置允许上传到文件后缀名,比如设置为.png,这样理论上webuploader可以选择一张.jpg的图片提交,但是在服务端会提示上传失败,然而,weuploader的uploadSuccess依然会判断为文件上传成功,因此,在处理uploadSuccess时间的响应时,增加了一层根据响应的json内容的判断。

4、服务端的接口代码

基于CodeIgniter的框架,只需要在控制器中增加一个webuplaoder方法就可以了,代码如下

    public function webuploader()
    {
        $config['upload_path']      = './uploads/proj';
        $config['allowed_types']    = 'doc|docx|pdf|ppt|jpg|png';
        $config['max_size']     = 10000;
        $config['file_ext_tolower'] = TRUE;
        $config['overwrite'] = TRUE;
        $config['encrypt_name'] = TRUE;
        $this->load->library('upload', $config);      
        $this->output->set_header('Content-Type: application/json;charset=utf-8');
        if ( ! $this->upload->do_upload('file'))
        {
            $error = array('error' => $this->upload->display_errors());
            echo '{"jsonrpc" : "2.0", "code": 101, "message": "'.implode($error).'"}';
        }  else
        {
            $upload_data = $this->upload->data();
            $uploads = $upload_data['full_path'];
            $uploads = str_replace(str_replace('\','/',  getcwd()), '', $uploads);
            echo '{"jsonrpc" : "2.0", "code": 201, "message": "'.$uploads.'"}';
        }        
    }

这一段里的$config是upload的配置,包括上传的文件夹,运行上传的文件类型,以及最大可以上传的文件大小,然后根据上传的结果返回成功或者失败的json。

总结

以上就是基于CodeIgniter框架作为后端脚本,结合Web Uploader上传组件制作无刷新文件上传的全部过程。其特点除了可以无刷新上传文件,由于Web Uploader支持大文件分割成小的文件块上传,这样可以避免服务器端php上传文件最大值的限制,还有双重的文件上传类型设置,完美的杜绝了非允许文件类型的上传。

喜欢请常来,打赏请随意。

  1. wu先生    回复

    技术文,不懂。
  2. agiga    回复

    服务端的接口代码,能提供多图上传的信息写入数据库的代码吗?万分感谢
  3. 安满    回复

    @agiga:多图上传的服务端代码没有专门的。因为在上传多个图片的时候,是由webuploader控制的,每个图片都交给上面那段上传代码处理。