综述

ImageUploader继承于Uploader,用于解决Uploader过于复杂,调用不便的问题,ImageUploader专门用于图片上传,自带图片验证,改进了伪属性配置方式。

PS: 如果是图片上传,不再建议使用Uploader,也不再建议用户自己设置type来控制上传方式。

ImageUploader的特性

  • 支持ajax、flash、iframe三方案,兼容所有浏览器。(iframe不推荐使用)
  • 多主题支持,可以自己定制主题
  • 支持多选批量上传
  • 支持上传进度显示
  • 支持取消上传
  • 支持图片预览(使用flash上传不支持)
  • 支持上传验证
  • 多种配置方式

demo汇总

文档内容非常详实,为了方便大家快速使用,将文档中的demo做了提取,即拿即用。

ImageUploader内置的主题

3种方式初始化组件

gallery的包配置是必不可少:

KISSY.config({
    packages:[
        {
            name:"gallery",
            path:"http://a.tbcdn.cn/s/kissy/",
            charset:"utf-8"
        }
    ]
});
            

1.使用js配置初始化组件

KISSY.use('gallery/form/1.3/uploader/imageUploader', function (S, ImageUploader) {

    new ImageUploader('#J_JsUploaderBtn','#J_JsUploaderQueue',{
        // 文件域
        name:"Filedata",
        //处理上传的服务器端脚本路径
        action:"upload.php",
        //用于放服务器端返回的url的隐藏域
        urlsInputName:"jsImageUrls"
    }).render();
})
            

配置参数说明

参数名 类型 默认值 描述
action String "" 服务器端处理上传的路径
name String Filedata 文件上传域name名,服务器端通过name来获取和处理上传数据
urlsInputName String '' 用于存放服务器端返回的文件路径的input(type="hidden"),当页面内不存在这个input时,组件会自动创建一个
PS: 这三个配置是最核心的配置,一般是必不可少,更多的接口说明请看API doc,后面将逐步介绍更多API。

2.使用标签属性配置初始化

1) 需要个input标签(type="image-uploader")

                
             
属性 描述
type="image-uploader" 此属性为了配合Butterfly使用,表明此input为图片上传专用组件
id="J_UploaderBtn" 脚本实例化上传组件时使用的钩子
name="Filedata" 非常重要,文件上传域name名,服务器端通过name来获取和处理上传数据
value="上传图片" 上传按钮上的文案

2) 创建一个input(hidden)用于存放服务器端返回的url

                    
             

给上传按钮input加上urlsInputName="imageUrls"属性,这样当上传成功后图片url会被加入到这个隐藏域中(多个图片路径以逗号隔开)。

3) 创建一个空的图片队列

                    

    给上传按钮input加上queueTarget="#J_UploaderQueue"属性,将上传按钮和上传队列关联起来,当选择完图片后,自动显示图片。

    4) 配置服务器端参数

    上传组件必须有服务器端脚本配合,所以需要个服务器端路径。可以使用action属性。

    可能你还需要向服务器post一些参数,比如用户名,商品id等,可以使使用postData='{"author":"明河"}'

    5) demo中完整的html结构

                        

    6) 初始化ImageUploader

    配置下gallery包路径(为了利用淘宝cdn,可以快速引用butterfly库,所以将代码托管在kissy gallery下)。

                    var S = KISSY,
                          path = "http://a.tbcdn.cn/s/kissy/";
                    KISSY.config({
                        packages:[
                            {
                                name:"gallery",
                                path:path,
                                charset:"utf-8"
                            }
                        ]
                    });
                

    初始化ImageUploader:

                KISSY.use('gallery/form/1.3/uploader/imageUploader', function (S, ImageUploader) {
                    new ImageUploader('#J_UploaderBtn').render();
                })
                
    当实例化ImageUploader时,组件会自动加载主题js和css文件,比如没用theme属性时,加载默认主题theme="imageUploader"gallery/form/1.3/uploader/themes/imageUploader/index-min.jsgallery/form/1.3/uploader/themes/imageUploader/style.css

    与服务器端的交互

    服务器端处理异步上传跟同步上传没太大区别,核心的操作是获取前端post到服务器端的数据,比如前端post的文件域name为Filedata,服务器端处理Filedata内的文件数据即可。

    服务器端处理完上传(无论是成功还是失败),需要返回一个json结果集,格式如下:

    上传成功时
                        {"status":1,"data":{"name":"minghe.jpg","url":"www.36ria.com/minghe.jpg"}}
                    
    上传失败时
                       {"status":0,"message":"图片过大!"}
                    
    PS:留意引号!!!特别是键名要加"",不然json会解析失败。
    PS:"status":1,才是上传成功的标识,其他任何状态码都认定为失败。

    demo php可以看 源码

    PS:文件上传成功后,组件会自动提取url放进urlsInputName配置的隐藏域内。

    如何向服务器端post额外的数据?

    使用js传参方式,增加post配置项即可,比如下面的代码:

    KISSY.use('gallery/form/1.3/uploader/ImageUploader', function (S, ImageUploader) {
        var imageUploader = new ImageUploader('#J_UploaderBtn', '#J_UploaderQueue',{
            data:{userName:"minghe",email:"minghe36@126.com"},
            name:"Filedata",
            urlsInputName:"fileUrls"
        });
    })
                

    如果是使用属性传参,在input上增加postData(不是data)属性即可,比如下面代码:

    
    
    留意引号.

    如何通过脚本动态修改post数据?

    imageUploader.on('render',function(ev){
        var uploader = ev.uploader;
        uploader.set('data',{userName:"ziying",email:"daxingplay@gmail.com"})
    })
    

    通过setdata属性值来动态修改post到服务器端数据。

    如果服务器返回的数据结构不符合解析要求,如何处理呢?

    1.3后Uploader新增filter属性,可以通过这个过滤器,重新map下丢给组件处理的数据。

    uploader.set('filter',function(data){
        data = S.JSON.parse(data);
        //unicode自动转换测试
        data.author = '\u660e\u6cb3';
        return data;
    })
                

    服务器端如何根据上传类型来做些返回数据的差异处理呢?

    典型的使用场景如下:flash上传,服务器返回的中文错误消息,打印到页面中时会乱码,这时候需要服务器端根据上传类型,在flash上传的情况下,将中文打印成unicode的编码,比如明河,输出为\u660e\u6cb3。

    组件会自动会post上传方式到服务器端,字段为type

    1.3开始Uploader会自动对unicode进行转码。

    如何处理服务器返回的错误消息?

    可以监听uploader的error事件,然后处理出错消息,比如下面的代码:

    uploader.on('error',function(ev){
        var result = ev.result;
        alert(result.msg);
    })
                

    IE下上传失败的处理

    IE下是使用flash上传方式,依赖于flash的安全策略crossdomain.xml,flash上传常见问题,可以看《flash(IE)上传问题汇总》

    如果你在使用uploader中遇到IE下进度条不走的情况,多半的原因是由于在域名根目录下没有放跨域策略文件crossdomain.xml导致的。

    以淘宝网的跨域策略为例:

                
                
                     
                    
                    
                
            

    tbcdn.cn为swf文件所在的位置,安全策略文件需要加上。

    当不存在crossdomain.xml文件时,控制台会打印错误消息,比如:

    上传成功后,会打印服务器返回的json数据,比如:

    上传验证控制

    组件的验证配置信息:

    var authImageUploader = new ImageUploader('#J_AuthBtn','#J_AuthQueue',{
        action:"upload.php",
        urlsInputName:"authImageUrls"
    });
    authImageUploader.on('render',function(ev){
        var uploader = ev.uploader;
        var max = uploader.get('max');
        var required = uploader.get('required');
        var allowExts = uploader.get('allowExts');
        var maxSize = uploader.get('maxSize');
    
    
        $('.J_AuthMsg').text('max:'+max + ',required:' + required + ',allowExts:' + allowExts + ',maxSize:' + maxSize);
    
        $('#J_TestRequired').on('click',function(ev){
            var isPass = uploader.testRequired();
            alert(isPass);
        });
    
        $('#J_TestMax').on('click',function(ev){
            var isPass = uploader.testMax();
            alert(isPass);
        });
    });
    authImageUploader.render();
                

    支持的验证规则

    规则名 默认值 描述
    allowExts jpg,jpeg,png,gif,bmp 图片格式验证控制,ImageUploader自带此验证。
    required true 必须至少上传一个文件
    组件默认不触发,可以使用uploader的testRequired()方法手动验证。
    max 3 最多上传N个图片,当达到N个图片后按钮会增加禁用样式uploader-button-disabled,用户可以通过这个样式名定制需要的置灰样式。
    可以用uploader.get('max')来获取该配置项值。
    maxSize 1024 单图片最大允许上传的文件大小,单位是KB
    如果是iframe上传方式,此验证无效。
    allowRepeat false 是否允许多次上传同一个文件
    不推荐增加这个验证,比较粗糙,只是根据文件名来做重复判断。

    如何配置验证?

    1) 伪属性配置方式:

                        
                

    2) js配置方式:

    var authImageUploader = new ImageUploader('#J_AuthBtn','#J_AuthQueue',{
        maxSize: 500,
        max:4,
        allowExts:"png",
        required,
        authMsg:{
            max:'每次最多上传{max}个图片!',
            maxSize:'图片大小为{size},超过{maxSize}!',
            required:'至少上传一张图片!',
            require:'至少上传一张图片!',
            allowExts:'不支持{ext}格式图片!'
        }
    });
                

    authMsg用于配置验证消息,一般采用默认的即可。

    如何获取和设置验证配置?

    想要获取验证配置非常简单,获取uploader对应的属性即可:

    authImageUploader.on('render',function(ev){
        var uploader = ev.uploader;
        var max = uploader.get('max');
        var required = uploader.get('required');
        var allowExts = uploader.get('allowExts');
        var maxSize = uploader.get('maxSize');
    });
    
    留意不是获取ImageUploader的属性,而是先监听render事件,然后监听ev.uploader

    设置验证配置,同样简单,使用uploader的set方法,比如uploader.set('max',5)

    如何在外部验证max和required?

    可以使用uploader.testMax()uploader.testRequired(),比如下面的代码:

    $('#J_TestRequired').on('click',function(ev){
        var isPass = uploader.testRequired();
        alert(isPass);
    });
    
    $('#J_TestMax').on('click',function(ev){
        var isPass = uploader.testMax();
        alert(isPass);
    });
                

    监听error出错事件

    当验证没有通过时,会触发uploader的error事件,示例代码如下:

    uploader.on('error',function(ev){
        var rule = ev.rule, msg = ev.msg,status = ev.status;
        if (rule == 'max') {
            alert(msg);
        }
        if(status === -1){
            alert('前端验证错误');
        }
    })
                

    如何渲染默认队列数据?

    在实际应用中通常会有个需求:用户已经上传了三张图片,然后保存,那么用户再进入这个页面时,应该如何展示这三张图片呢?

    这里有个难点,我们需要把图片插入到组件的队列中,这样文件数的统计、删除等行为才是一致的。

    只要开发将图片的url打印到urlsInput隐藏域中即可,组件会自动渲染,比如下面的代码:

                     
                

    如何使用其他主题

    使用refundUploader主题,增加个属性theme="refundUploader",该主题是从淘宝退款的上传凭证提炼出来的。

    使用js传参方式,加上theme:"refundUploader"即可。

    内置的主题,无法满足实际的需求场景,还可以自制主题,可以看《如何制作属于自己的主题》

    事件演示

    ImageUploader支持的所有事件

    事件名 描述
    select 选择完文件后触发
    add 向队列添加完文件后触发
    start 开始上传后触发
    progress 正在上传中时触发,这个事件在iframe上传方式中不存在
    success 上传成功后触发
    error 上传失败后触发
    cancel 取消上传后触发
    restore 渲染默认队列数据结束后触发
    remove 删除队列中的图片后触发
    statusChange 队列中的图片上传状态发生改变后触发

    用法举例

    var imageUploader2 = new ImageUploader('#J_UploaderBtn2', '#J_UploaderQueue2');
    imageUploader2.on('render', function (ev) {
        addMsg(ev, '上传组件准备就绪!');
    });
    imageUploader2.on('select', function (ev) {
        var files = ev.files;
        addMsg(ev, '选择了' + files.length + '个文件');
    });
    imageUploader2.on('start', function (ev) {
        var index = ev.index, file = ev.file;
        addMsg(ev, '开始上传,文件名:' + file.name + ',队列索引为:' + index);
    });
    imageUploader2.on('progress', function (ev) {
        var file = ev.file, loaded = ev.loaded, total = ev.total;
        addMsg(ev, '正在上传,文件名:' + file.name + ',大小:' + total + ',已经上传:' + loaded);
    });
    imageUploader2.on('success', function (ev) {
        var index = ev.index, file = ev.file;
        //服务器端返回的结果集
        var result = ev.result;
        addMsg(ev, '上传成功,服务器端返回上传方式:' + result.type);
    });
    imageUploader2.on('complete', function (ev) {
        var index = ev.index, file = ev.file;
        //服务器端返回的结果集
        var result = ev.result;
        addMsg(ev, '上传结束,服务器端返回上传状态:' + result.status);
    });
    imageUploader2.on('error', function (ev) {
        var index = ev.index, file = ev.file;
        //服务器端返回的结果集
        var result = ev.result;
        addMsg(ev, '上传失败,错误消息为:' +result.msg);
    });
    imageUploader2.on('add',function(ev){
        var queue = ev.queue;
        var file = ev.file;
        addMsg(ev, '队列添加文件!文件名为:'+file.name);
    });
    imageUploader2.on('remove',function(ev){
        var queue = ev.queue;
        addMsg(ev, '队列删除文件!文件索引值:'+ev.index);
        alert('队列中的文件数为:'+queue.get('files').length);
    });
    imageUploader2.render();
            

    所有的事件对象(ev)都带有Uploader和queue的实例,可以通过ev.uploaderev.queue来控制上传和队列。

    多选/禁用/立即上传控制

    使用js传参的配置方式:

    var imageUploader3 = new ImageUploader('#J_UploaderBtn3', '#J_UploaderQueue3',{
        autoUpload: false,
        multiple:false,
        disabled:true
    });
    imageUploader3.render();
            

    html标签属性配置方式:

                    
            
    留意:设置disabled="false"无效

    接口说明

    参数名 类型 默认值 描述
    autoUpload Boolean true 是否自动上传,当为false时,可以通过uploader的upload()uploadFiles()手动上传队列中的文件。
    multiple Boolean true 是否开启多选支持
    如果采用iframe上传,请设置为false
    disabled Boolean false 是否可用,false为按钮可用

    通过uploader的set方法手动改变这三个状态

    用法举例:

    imageUploader3.on('render',function(ev){
        var uploader = ev.uploader;
        $('#J_Disabled').on('change',function(ev){
            var isChecked = $(ev.target).prop('checked');
            uploader.set('disabled',isChecked);
        });
        $('#J_Multiple').on('change',function(ev){
            var isChecked = $(ev.target).prop('checked');
            uploader.set('multiple',isChecked);
        });
        $('#J_UploadAll').on('click',function(){
            uploader.uploadFiles();
        })
    });
            
    uploadFiles()方法为上传所有队列中等待的文件。

    queue(队列实例)控制

    queue的详细API请看文档

    示例

    想要操作队列,就必须先获取Queue实例,比如下面的代码:

        //uploaderQueueTest为RenderUploader的实例
        uploaderQueueTest.on('render',function(ev){
           var queue = ev.queue;
        });
        

    下面举例说明常用的方法和属性。

    add():向队列添加文件

               $('#J_Add').on('click', function (ev) {
                //测试文件数据
                var testFile = {'name':'test.jpg',
                    'size':2000,
                    'input':{},
                    'file':{'name':'test.jpg', 'type':'image/jpeg', 'size':2000}
                };
                //向队列添加文件
                var file = queue.add(testFile);
                S.log('添加的文件数据为:'+file);
            });
        

    remove():删除队列中的文件

               $('#J_DelFirst').on('click', function (ev) {
                    var removeFile = queue.remove(0);
                    S.log('删除的文件数据为:'+removeFile);
                });
        
    留意remove()的参数可以是队列数组的索引,比如上面代码的0,是取队列第一个文件数据;也可以是文件的id(唯一),比如remove('file-26')

    fileStatus(index, status, args):改变文件状态

    默认的主题共有以下文件状态:'waiting'、'start'、'progress'、'success'、'cancel'、'error'

    不同的主题拥有的状态情况可能存在差异。

           $('#J_ChangeStatus').on('click', function (ev) {
                queue.fileStatus(0, 'success');
            });
        

    clear():删除队列内的所有文件

           $('#J_Clear').on('click', function (ev) {
            queue.clear();
            });
        

    files:通过该属性可以获取队列中所有的文件数据

               $('#J_GetAll').on('click', function (ev) {
                    var ids = [],
                            files = queue.get('files');
                    S.each(files, function (file) {
                        ids.push(file.id);
                    });
                    alert('所有文件id:' + ids);
                });
        

    getFiles(type):获取指定状态下的文件

           $('#J_GetStatusFileIds').on('click', function (ev) {
                var files = queue.getFiles('waiting'),
                        ids = [];
                S.each(files, function (file) {
                    ids.push(file.id);
                });
                alert('所有等待中的文件id为:' + ids);
            });
        

    getIndexs(type):获取等指定状态的文件对应的文件数组索引值组成的数组

    getFiles()和getFileIds()的作用是不同的,getFiles()类似过滤数组,获取的是指定状态的文件数据,而getFileIds()只是获取指定状态下的文件对应的在文件数组内的索引值。

           $('#J_GetStatusFilesIndex').on('click', function () {
                var indexs = queue.getIndexs('waiting');
                alert('所有等待中的文件index为:' + indexs);
            })
        

    uploader常用方法

    upload (index)

    上传指定队列索引的文件。

    //上传队列中的第一个文件,uploader为Uploader的实例
    uploader.upload(0)
    

    uploadFiles (status)

    批量上传队列中的指定状态下的文件。

    //上传队列中所有等待的文件
    uploader.uploadFiles("waiting")
    

    cancel (index)

    取消文件上传,当index参数不存在时取消当前正在上传的文件的上传。cancel并不会停止其他文件的上传(对应方法是stop)。

    //取消当前正在上传的文件的上传
    uploader.cancel();
    

    stop():停止上传动作

    //停止上传
    uploader.stop();
    

    testMax():验证图片是否已经达到最大允许上传数

    //return false | true;
    uploader.testMax();
    

    testRequired():验证是否至少上传了一个文件

    //return false | true;
    uploader.testRequired();
    

    uploader常用属性/配置

    uploader的配置都会写入成uploader的属性内。uploader的几个关键配置前面都有提到了,这里做个汇总。

    属性名 类型 默认值 是否只读 描述
    type 不推荐使用 String|Array "auto" 只读 采用的上传方案,当值是数组时,比如“type” : ["flash","ajax","iframe"],按顺序获取浏览器支持的方式,该配置会优先使用flash上传方式,如果浏览器不支持flash,会降级为ajax,如果还不支持ajax,会降级为iframe;当值是字符串时,比如“type” : “ajax”,表示只使用ajax上传方式。这种方式比较极端,在不支持ajax上传方式的浏览器会不可用;
    当“type” : “auto”,auto是一种特例,等价于["ajax","flash","iframe"]。
    不再推荐配置type,除非在使用flash时遇到难以解决的问题。
    curUploadIndex Number "" 只读 当前上传的文件对应的在数组内的索引值,如果没有文件正在上传,值为空
    isAllowUpload Boolean true 只读 是否允许上传文件
    queue Queue '' 只读 Queue队列的实例,想要对队列进行操作或监听队列的事件,就必须先获取这个属性
    restoreHook String '' 只读 已经存在的文件数据待提取的容器钩子,用法请看默认数据展现
    autoUpload Boolean true 读/写 是否自动上传,当为false时,可以通过uploader的upload()uploadFiles()手动上传队列中的文件。
    multiple Boolean true 读/写 是否开启多选支持
    如果采用iframe上传,请设置为false
    multipleLen Number -1 读/写 用于限制多选文件个数,值为负时不设置多选限制(v1.2.6+)
    disabled Boolean false 读/写 是否可用,false为按钮可用
    serverConfig 弃用 Object {action:'', data:{}, dataType:'json'} 读/写 服务器端配置,包括最重要的action(路径)配置,data为post到服务器端数据
    action String '' 读/写 服务器端处理上传的路径(v1.3.0+)
    data Object {} 读/写 此配置用于动态修改post给服务器的数据,会覆盖serverConfig的data配置(v1.2.6+)
    name String Filedata 只读 文件上传域name名
    urlsInputName String '' 只读 用于存放服务器端返回的文件路径的input(type="hidden")
    max Number 3 读/写 最多上传N张图片,没有配置该项验证时不存在(v1.3.0+)
    maxSize Number 1024 读/写 单文件最大允许上传的文件大小,单位是KB,没有配置该项验证时不存在(v1.3.0+)
    required Boolean false 读/写 必须至少上传一个文件,没有配置该项验证时不存在(v1.3.0+)
    allowExts String 'jpg,jpeg,png,gif,bmp' 读/写 文件格式验证,没有配置该项验证时不存在(v1.3.0+)
    allowRepeat Boolean false 读/写 是否允许多次上传同一个文件,没有配置该项验证时不存在(v1.3.0+)