上传插件之----Web Uploader

最近云盘要大改版,前端采用了谷歌的AngularJS框架。大改嘛,之前云盘用插件要换的也都要换。飞哥说插件可以用但是却不能乱用,尤其是将其用于商业领域的,必须慎重加慎重,首先选选择的插件得符合相关的开原协议(如上篇),因滥用别的插件而上法庭的例子举不胜数。作为小菜的我一直都以够用,管用,好用的心态去用这些插件的,什么开原协议啊,什么版权啊之类的,不懂~大神告诉我,这个很重要,因为一旦被查出,后果很严重。。。飞哥推荐使用以MIT开源协议发布的Web Uploader作为上传插件。研究了它几天,苦恼,痛苦,桑心…

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

1
2
3
4
5
6
分片、并发  
预览、压缩  
多途径添加文件   
HTML5 & FLASH  
MD5秒传   
易扩展,可拆分     

看着介绍貌似很吊,于是demo走起….
官网的第一个demo就把我给吓尿了,这文档也太简单了吧!!!据飞哥说他们团队游50多人,我只想说你们把文档写这么简单你家人知道吗???照着做本地硬是跑不通!无奈只能在它官网F12(>_<)

一、引入JS、css。webuploader.js可以在官网在下载,cloudupload.js是上传前各参数的初始化及上传结果处理,bootstrap.min.cssbootstrap框架的核心文件,可以在官网下载:

1
2
3
<link rel="stylesheet" href="libs/bootstrap/css/bootstrap.min.css"/>
<script type="text/javascript" src="libs/webupload/webuploader.js"></script>
<script type="text/javascript" src="libs/webupload/cloudupload.js"></script>

二、html模块,包含存放文件信息的容器、选择按钮和上传按钮三个部分。

1
2
3
4
5
6
7
8
<div id="uploader" class="wu-example">
    <!--用来存放文件信息-->
    <div id="thelist" class="uploader-list"></div>
    <div class="btns">
        <div id="picker">选择文件</div>
        <button id="ctlBtn" class="btn btn-default">开始上传</button>
    </div>
</div>

三、初始化上传参数(webuploader.js)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
var $ = jQuery,
$list = $('#thelist'),
$btn = $('#ctlBtn'),
state = 'pending'; //上传状态
window.fileList = []; //获取要上传的文件列表数组
var uploader = WebUploader.create({
    // swf文件路径
    swf: '/web2/libs/webupload/Uploader.swf',
    // 文件接收服务端。
    server: 'http://webuploader.duapp.com/server/fileupload.php',
    // 选择文件的按钮。可选。
    // 内部根据当前运行是创建,可能是input元素,也可能是flash.
    pick: id,

    // 不压缩image, 默认如果是jpeg,文件上传前会压缩一把再上传!
    resize: false
});

//当有文件被添加进队列的时候
uploader.on( 'fileQueued', function( file ) {
  //发送ajax请求道后台 返回从后台拼装的SAL上传url
  $.ajax({
      type : 'POST',
      url : '/cloud-web/upload/getUploadUrl.htm',
      data: {
          "fileName": file.name,
          "folderId": window.currentFolderId,
          "size": file.size
      },
      dataType: 'json',
      success: function(data){
          file.server = data.uploadUrl;
          console.log("sal url------->" + data.uploadUrl);
      },
      error : function(data){
          //错误提示
          console.log("获取上传地址错误...");
      }
    });
  fileList.push(file); //将要上传的文件加入fileList数组
  $list.append( '<div id="' + file.id + '" class="item">' +
        '<h4 class="info">' + file.name + '</h4>' +
        '<p class="state">等待上传...</p>' +
    '</div>' );
});

//文件上传过程中创建进度条实时显示。
uploader.on( 'uploadProgress', function( file, percentage ) {
    var $li = $( '#'+file.id ),
        $percent = $li.find('.progress .progress-bar');
    // 避免重复创建
    if ( !$percent.length ) {
        $percent = $('<div class="progress progress-striped active">' +
          '<div class="progress-bar" role="progressbar" style="width: 0%">' +
          '</div>' +
        '</div>').appendTo( $li ).find('.progress-bar');
    }
    $li.find('p.state').text('上传中');
    $percent.css( 'width', percentage * 100 + '%' );
    $percent.attr( 'uploadProgress', percentage);
});

//文件上传完成
uploader.on( 'uploadComplete', function( file ) {
  //上传完成隐藏进度条
  $( '#'+file.id ).find('.progress').fadeOut();
});
//文件上传成功
uploader.on( 'uploadSuccess', function( file ) {
  $( '#'+file.id ).find('p.state').text('已上传');
});
//文件上传失败
uploader.on( 'uploadError', function( file ) {
  $( '#'+file.id ).find('p.state').text('上传出错');
});
//文件上传各个部分监听
uploader.on( 'all', function( type ) {
    if ( type === 'startUpload' ) {
        state = 'uploading';
    } else if ( type === 'stopUpload' ) {
        state = 'paused';
    } else if ( type === 'uploadFinished' ) {
        state = 'done';
    }
});
//按钮添加监听事件
$btn.on( 'click', function() {
    if ( state === 'uploading' ) {
        uploader.stop();
    } else {
        uploader.upload();
    }
});

蛋疼的紧,官网demo代码少的可怜~ 效果见官网。

紧接着遇到第二个难题,云盘现在文件上传采用的是SAL(存储访问层)模式,即每一个文件都要从服务端获取一个上传点,然后上传插件在向上传点进行上传操作。这里就存在一个问题,从上面我们发现要进行上传操作我们需要创建Web Uploader实例:WebUploader.create{…},我们发现在创建实例的时候需要传入一个文件接收服务端server,这就遇到了难题,我们上传模式是一个文件对应一个上传URL,而次插件又没有提供类似的方法可以动态修改每个server对应的值。经过不懈的努力外加看源码再加各种测试,终于搞定了~··

首先,定义一个全局数组window.fileList = [];用于获取要上传的文件列表数组,然后在文件加入队列的时候对数组进行push操作:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
//当有文件被添加进队列的时候
uploader.on( 'fileQueued', function( file ) {
  //发送ajax请求道后台 返回从后台拼装的SAL上传url
  $.ajax({
      type : 'POST',
      url : '/cloud-web/upload/getUploadUrl.htm',
      data: {
          "fileName": file.name,
          "folderId": window.currentFolderId,
          "size": file.size
      },
      dataType: 'json',
      success: function(data){
          file.server = data.uploadUrl;
          console.log("sal url------->" + data.uploadUrl);
      },
      error : function(data){
          //错误提示
          console.log("获取上传地址错误...");
      }
    });
  fileList.push(file); //将要上传的文件加入fileList数组
  $list.append( '<div id="' + file.id + '" class="item">' +
        '<h4 class="info">' + file.name + '</h4>' +
        '<p class="state">等待上传...</p>' +
    '</div>' );
});

file.server = data.uploadUrl;给每一个file对象增加一个该filefile对象对应的上传URL,fileList.push(file);将所有要上传的文件放入数组。接下来就是修改webUpload.js源码。定位webUpload.js第3876行,修改如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
send: function() {
    var owner = this.owner,
        opts = this.options,
        xhr = this._initAjax(),
        blob = owner._blob,
        formData, binary;
    
    //将上传队列中的第一个文件的数组的上传地址放入server
    //window.fileList.length 变量在cloudupload中定义
    var server;
  for(var i = 0 ;i < window.fileList.length; i++){
      if(window.fileList[i].id == opts.formData.id){
          server = window.fileList[i].server;
      }
  }
    ....
    ....

此处遍历了window.fileList,根据每一个file对象的id进行匹配对应的上传URL

到这里就基本OK了,看起来简单,可当初找起来真费事儿,头疼~~~,之后文件上传还遇到跨域问题,因为文件上传的服务器与服务端不是同一域名下,所以会出现跨域问题。经ngnix修改相关配置后将问题解觉…

文章评论

返回顶部