<!doctype html>
|
<html>
|
<head>
|
<meta charset="utf-8"/>
|
<title>KF/Uploader</title>
|
<link rel="shortcut icon" href="http://docs.kissyui.com/kissy-dpl/base/assets/favicon.ico"/>
|
<link rel="stylesheet" type="text/css" href="../../assets/bootstrap.min.css"/>
|
<link rel="stylesheet" type="text/css" href="../../assets/bootstrap-responsive.css"/>
|
<link rel="stylesheet" type="text/css" href="../../assets/docs.css"/>
|
<script src="http://a.tbcdn.cn/s/kissy/1.2.0/kissy.js" charset="utf-8"></script>
|
<script src="../../assets/feedback.js" charset="utf-8"></script>
|
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js" charset="utf-8"></script>
|
<script src="http://bootswatch.com/assets/js/bootstrap-dropdown.js" charset="utf-8"></script>
|
<script src="http://bootswatch.com/assets/js/bootstrap-scrollspy.js" charset="utf-8"></script>
|
<script src="../../assets/app.js" charset="utf-8"></script>
|
</head>
|
<body data-spy="scroll" data-target=".subnav" data-offset="50">
|
<div class="navbar navbar-fixed-top">
|
<div class="navbar-inner">
|
<div class="container">
|
<a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
|
<span class="icon-bar"></span>
|
<span class="icon-bar"></span>
|
<span class="icon-bar"></span>
|
</a>
|
<a class="brand" href="http://www.36ria.com/demo/gal/gallery/form/1.3/demo.html" id="logo">BUTTERFLY</a>
|
|
<div class="nav-collapse">
|
|
<ul class="nav">
|
<li><a href="http://docs.kissyui.com/kissy-gallery/gallery/form/1.3/demo.html">首页</a></li>
|
<li class="dropdown"><a class="dropdown-toggle" data-toggle="dropdown" href="#">组件 <b
|
class="caret"></b></a>
|
<ul class="dropdown-menu">
|
<li><a href="http://www.36ria.com/demo/gal/gallery/form/1.3/demo/form/uploader/index.html">Uploader</a>
|
</li>
|
<li class=""><a
|
href="http://www.36ria.com/demo/gal/gallery/form/1.3/demo/form/limiter/index.html">Limiter</a>
|
</li>
|
<li><a href="http://www.36ria.com/demo/gal/gallery/form/1.3/demo/form/spinbox/index.html">SpinBox</a>
|
</li>
|
<li>
|
<a href="http://www.36ria.com/demo/gal/gallery/form/1.3/demo/form/auth/index.html">Auth</a>
|
</li>
|
<li class=""><a
|
href="http://www.36ria.com/demo/gal/gallery/form/1.3/demo/form/checkbox/index.html">checkbox</a>
|
</li>
|
<li class=""><a
|
href="http://www.36ria.com/demo/gal/gallery/form/1.3/demo/form/radio/index.html">radio</a>
|
</li>
|
</ul>
|
</li>
|
<li><a href="https://github.com/kissyteam/kissy-gallery/tree/master/gallery/form">源码</a></li>
|
<li><a href="http://www.36ria.com/demo/gal/gallery/form/1.3/doc/index.html">API文档</a></li>
|
</ul>
|
<ul class="nav pull-right">
|
<li><a rel="tooltip" target="_blank" href="http://docs.kissyui.com/kissy-gallery/index.html">kissy
|
gallery</a></li>
|
</ul>
|
</div>
|
</div>
|
</div>
|
</div>
|
<div class="container">
|
<header id="header" class="jumbotron subhead">
|
<h1 class="title-h1">Uploader
|
<small>异步文件上传组件</small>
|
</h1>
|
|
<div class="subnav">
|
<ul class="nav nav-pills">
|
<li class="active"><a href="#use">调用</a></li>
|
<li><a href="#server">服务器端交互</a></li>
|
<li><a href="#crossdomain">IE的crossdomain</a></li>
|
<li><a href="#auth">上传验证</a></li>
|
<li><a href="#theme">主题使用</a></li>
|
<li><a href="#defaultData">默认数据展现</a></li>
|
<li><a href="#button">按钮控制</a></li>
|
<li><a href="#queue">队列控制</a></li>
|
<li><a href="#api">常用API</a></li>
|
<li><a href="#plugins">关于插件</a></li>
|
</ul>
|
</div>
|
<div class="dec">
|
<p>
|
作者:明河(剑平)、紫英、飞绿
|
</p>
|
|
<p><strong>Uploader</strong>是一个基于kissy1.2的异步文件上传组件,目前不兼容kissy1.1.6,已经实现ajax、iframe、flash三方案异步上传,已经广泛应用于淘宝系统。
|
</p>
|
|
<p>(PS:flash上传方案改造自龙藏的ajbridge中的uploader,非常棒的实现,特此感谢。)</p>
|
</div>
|
|
<ul>
|
<li>支持ajax、flash、iframe三方案,兼容所有浏览器。</li>
|
<li>配置简单,支持伪属性配置(data-config=’{}’)和配置属性来配置</li>
|
<li>ajax和flash上传方式,带有上传进度显示</li>
|
<li>队列上传,批量上传等待中的文件</li>
|
<li>支持中途取消上传</li>
|
<li>支持上传验证,整合kissy的validation组件</li>
|
<li>不错的扩展性,自由定制按钮和队列模板样式</li>
|
</ul>
|
|
</header>
|
|
<div id="content">
|
<h2 id="use">最简单调用</h2>
|
|
<div class="row">
|
<div class="span4">
|
<h3>例子</h3>
|
|
<p>必须从服务器端浏览demo,demo中使用的服务器端脚本是php。
|
</p>
|
<a id="J_UploaderBtn" href="#upload"> 选择要上传的文件 </a>
|
<!-- 文件上传队列 -->
|
<ul id="J_UploaderQueue">
|
|
</ul>
|
|
<h3>html结构</h3>
|
<pre class='brush: xml; '>
|
<!-- 文件上传按钮 -->
|
<a id="J_UploaderBtn" href="#upload"> 选择要上传的文件 </a>
|
<!-- 文件上传队列 -->
|
<ul id="J_UploaderQueue">
|
|
</ul>
|
</pre>
|
<p>非常简单的html结构,一个上传按钮(必须)和一个文件队列(可以不存在)。</p>
|
|
<h3>生成的dom结构</h3>
|
|
<p>ajax上传方案(chrome/firefox)</p>
|
<pre class='brush: xml; '>
|
<a href="#" class="uploader-button defaultTheme-button" id="J_UploaderBtn">
|
选择要上传的文件
|
<div style="overflow: hidden;" class="file-input-wrapper">
|
<input type="file" style="font-size: 400px; " class="file-input" hidefocus="true"
|
name="fileInput">
|
</div>
|
<input type="hidden" value="" name="fileUrls" id="fileUrls">
|
</a>
|
</pre>
|
<p>flash上传方案(IE)</p>
|
<pre class='brush: xml; '>
|
<a href="#" id="J_UploaderBtn" style="position: relative;">
|
选择要上传的文件
|
<div style="position: absolute; top: 0px; left: 0px; z-index: 2000;" class="uploader-button-swf"
|
id="swf-uploader-wrapper-67">
|
<embed width="110" height="24"
|
flashvars="btn=true&hand=true&jsEntry=KISSY.AJBridge.eventHandler&swfID=swfUploader"
|
allowscriptaccess="always" wmode="transparent" bgcolor="#fff"
|
type="application/x-shockwave-flash" id="swfUploader"
|
src="http://a.tbcdn.cn/s/kissy/gallery/form/1.1/uploader/plugins/ajbridge/uploader.swf">
|
</div>
|
<input type="hidden" value="" name="fileUrls" id="fileUrls">
|
</a>
|
</pre>
|
<div class="alert alert-info"><strong>PS:</strong> 相关详细说明请看<a href="http://www.36ria.com/5370" target="_blank">《关键点说明—KF/Uploader快速使用指南》</a>
|
</div>
|
</div>
|
<div class="span8">
|
<h3>javascript代码</h3>
|
|
<p>配置下gallery的包路径</p>
|
<pre class='brush: js; '>
|
KISSY.config({
|
packages:[ {
|
name:"gallery",
|
path:"http://a.tbcdn.cn/s/kissy/",
|
charset:"utf-8"
|
} ]
|
});
|
</pre>
|
<p>初始化上传组件</p>
|
<pre class='brush: js; '>
|
KISSY.use('gallery/form/1.3/uploader/index', function (S, RenderUploader) {
|
new RenderUploader('#J_UploaderBtn', '#J_UploaderQueue',{
|
//服务器端配置
|
serverConfig:{
|
//处理上传的服务器端脚本路径
|
action:"upload.php"
|
},
|
// 文件域
|
name:"Filedata",
|
//用于放服务器端返回的url的隐藏域
|
urlsInputName:"fileUrls"
|
});
|
})
|
</pre>
|
|
<h3>配置参数说明</h3>
|
<table class="table table-bordered table-striped">
|
<thead>
|
<tr>
|
<th style="width: 100px;">参数名</th>
|
<th style="width: 50px;">类型</th>
|
<th style="width: 100px;">默认值</th>
|
<th>描述</th>
|
</tr>
|
</thead>
|
<tbody>
|
<tr>
|
<td>serverConfig</td>
|
<td>Object</td>
|
<td>{action:'', data:{}, dataType:'json'}</td>
|
<td>服务器端配置,包括最重要的<code>action</code>(路径)配置,<code>data</code>为post到服务器端数据
|
</td>
|
</tr>
|
<tr>
|
<td>name</td>
|
<td>String</td>
|
<td>Filedata</td>
|
<td>文件上传域name名,组件会根据这个name值生成一个文件上传input(type="file")
|
</td>
|
</tr>
|
<tr>
|
<td>urlsInputName</td>
|
<td>String</td>
|
<td>''</td>
|
<td>用于存放服务器端返回的文件路径的input(type="hidden")
|
</td>
|
</tr>
|
</tbody>
|
</table>
|
<div class="alert alert-info"><strong>PS:</strong> 这三个配置是最核心的配置,一般是必不可少,更多的接口说明请看<a
|
href="http://www.36ria.com/demo/gal/gallery/form/1.3/doc/symbols/Uploader.html" target="_blank">API
|
doc</a>,后面将逐步介绍更多API。
|
</div>
|
</div>
|
</div>
|
|
<h2 id="server">与服务器端的交互</h2>
|
|
<p>服务器端处理异步上传跟同步上传没太大区别,核心的操作是获取前端post到服务器端的数据,比如前端post的文件域<code>name</code>为Filedata,服务器端处理Filedata内的文件数据即可。</p>
|
|
<p>服务器端处理完上传(无论是成功还是失败),需要返回一个json结果集,格式如下:</p>
|
|
<div class="alert alert-success" style="width:250px;">上传成功时</div>
|
<pre class='brush: js; '>
|
{"status":1,"data":{"name":"minghe.jpg","url":"www.36ria.com/minghe.jpg"}}
|
</pre>
|
<div class="alert alert-error" style="width:250px;">上传失败时</div>
|
<pre class='brush: js; '>
|
{"status":0,"message":"图片过大!"}
|
</pre>
|
<div class="alert alert-info"><strong>PS:</strong>留意引号!!!特别是键名要加<code>""</code>,不然json会解析失败。</div>
|
<div class="alert alert-info"><strong>PS:</strong><code>"status":1</code>,才是上传成功的标识,其他任何状态码都认定为失败。</div>
|
<p>demo php可以看<a
|
href="https://github.com/kissyteam/kissy-gallery/blob/master/gallery/form/1.3/demo/form/uploader/upload.php"
|
target="_blank"> 源码</a>。</p>
|
|
<div class="alert alert-info"><strong>PS:</strong>文件上传成功后,组件会自动提取url放进<code>urlsInputName</code>配置的隐藏域内。</div>
|
<h3>动态修改post到服务器端的数据</h3>
|
|
<p>前面的demo,我们通过配置<code>serverConfig</code>来控制post到服务器端的数据,比如下面的代码:</p>
|
<pre class='brush: js; '>
|
KISSY.use('gallery/form/1.3/uploader/index', function (S, RenderUploader) {
|
var ru = new RenderUploader('#J_UploaderBtn', '#J_UploaderQueue',{
|
serverConfig:{
|
action:"upload.php",
|
data:{userName:"minghe",email:"minghe36@126.com"}
|
},
|
name:"Filedata",
|
urlsInputName:"fileUrls"
|
});
|
})
|
</pre>
|
<p>有时我们希望<code>data</code>参数是可以通过脚本动态配置,可以这么处理:</p>
|
<pre class='brush: js; '>
|
ru.on('init',function(ev){
|
var uploader = ev.uploader;
|
uploader.set('data',{userName:"ziying",email:"daxingplay@gmail.com"})
|
})
|
</pre>
|
<p>通过set<code>data</code>属性值来动态修改post到服务器端数据。</p>
|
<h2 id="crossdomain">IE下上传flash跨域处理</h2>
|
|
<p>如果你在使用uploader中遇到IE下进度条不走的情况,多半的原因是由于在域名根目录下没有放跨域策略文件<code>crossdomain.xml</code>导致的。</p>
|
|
<div class="alert alert-info"><strong>PS:</strong>IE下是使用flash上传,依赖于flash的安全策略crossdomain.xml</div>
|
<p>以淘宝网的跨域策略为例:</p>
|
<pre class='brush: xml; '>
|
<?xml version="1.0"?>
|
<cross-domain-policy>
|
<allow-access-from domain="*.tbcdn.cn"> </allow-access-from>
|
<allow-access-from domain="*.taobao.com"></allow-access-from>
|
<allow-access-from domain="*.taobao.net"></allow-access-from>
|
<allow-access-from domain="*.taobaocdn.com"></allow-access-from>
|
<allow-access-from domain="*.allyes.com"></allow-access-from>
|
</cross-domain-policy>
|
</pre>
|
<p>tbcdn.cn为swf文件所在的位置,安全策略文件需要加上。</p>
|
当不存在crossdomain.xml文件时,控制台会打印错误消息,比如:
|
<p><img src="http://www.36ria.com/wp-content/uploads/2012/05/uploader-v1.2.png"/></p>
|
上传成功后,会打印服务器返回的json数据,比如:
|
<p><img src="http://www.36ria.com/wp-content/uploads/2012/05/uploader-v1.2-2.png"/></p>
|
|
<h2 id="auth">异步上传的验证</h2>
|
|
<div class="row">
|
<div class="span4">
|
<h3>例子</h3>
|
<a id="J_UploaderAuthBtn" href="#upload"> 选择要上传的文件 </a>
|
<!-- 文件上传队列 -->
|
<ul id="J_UploaderAuthQueue">
|
|
</ul>
|
|
</div>
|
<div class="span8">
|
<h3>增加authConfig配置</h3>
|
<pre class='brush: js; '>
|
new RenderUploader('#J_UploaderAuthBtn', '#J_UploaderAuthQueue', {
|
serverConfig:{ action:"upload.php" },
|
name:"Filedata",
|
urlsInputName:"fileUrls",
|
//验证配置
|
authConfig: {
|
require:[true,"必须至少上传一个文件!"],
|
max:[3, "最多上传{max}个文件!"],
|
maxSize:[1000, "文件大小为{size},文件太大!"],
|
allowRepeat:[false, "该文件已经存在!"],
|
allowExts:[
|
{"desc":"JPG,JPEG,PNG,GIF,BMP", "ext":"*.jpg;*.jpeg;*.png;*.gif;*.bmp"},
|
"不支持{ext}格式的文件上传!"
|
]
|
}
|
});
|
</pre>
|
<h3>支持的验证规则</h3>
|
|
<div class="alert alert-info">每一项规则的值都必须为一个数组,数组的一个值为规则控制,第二个值为规则验证文案,比如<code>max:[3, "每次最多上传{max}个文件!"]</code>。
|
</div>
|
<table class="table table-bordered table-striped">
|
<thead>
|
<tr>
|
<th style="width: 100px;">规则名</th>
|
<th style="width: 200px;">举例</th>
|
<th>描述</th>
|
</tr>
|
</thead>
|
<tbody>
|
<tr>
|
<td>require</td>
|
<td>[true,"必须至少上传一个文件!"]</td>
|
<td>
|
必须至少上传一个文件
|
<div class="alert alert-info">上传必须性,默认不打印消息</div>
|
</td>
|
</tr>
|
<tr>
|
<td>max</td>
|
<td>[3, "最多上传{max}个文件!"]</td>
|
<td>
|
最多上传3个文件,当达到3个文件后按钮会增加禁用样式<code>uploader-button-disabled</code>,用户可以通过这个样式名定制需要的置灰样式。
|
<div class="alert alert-error">不推荐隐藏按钮,不可隐藏按钮的父容器。</div>
|
</td>
|
</tr>
|
<tr>
|
<td>maxSize</td>
|
<td>[1000, "文件大小为{size},文件太大!"]</td>
|
<td>
|
单文件最大允许上传的文件大小,单位是<code>KB</code>
|
|
<div class="alert alert-info">如果是iframe上传方式,此验证无效</div>
|
</td>
|
</tr>
|
<tr>
|
<td>allowRepeat</td>
|
<td>[false, "该文件已经存在!"]</td>
|
<td>是否允许多次上传同一个文件
|
<div class="alert alert-error">不推荐增加这个验证,比较粗糙,只是根据文件名来做重复判断</div>
|
</td>
|
</tr>
|
<tr>
|
<td>allowExts</td>
|
<td>[
|
{"desc":"JPG,JPEG,PNG,GIF,BMP", "ext":"*.jpg;*.jpeg;*.png;*.gif;*.bmp"},
|
"不支持{ext}格式的文件上传!"
|
]
|
</td>
|
<td>
|
非常常用的文件格式验证,基本上每个上传都会用到
|
<div class="alert alert-info"><strong>留意:</strong>数组第一个值是个object,<code>desc</code>为文件格式描述,只在IE(flash)下起作用。<code>ext</code>才是真正的文件过滤规则。
|
</div>
|
</td>
|
</tr>
|
</tbody>
|
</table>
|
<h3>监听error事件</h3>
|
|
<p>监听uploader的error事件即可(V1.2.6),比如下面的代码:</p>
|
<pre class='brush: js; '>
|
uploader.on('error', function (ev) {
|
var rule = ev.rule, msg = ev.msg,status = ev.status;
|
if (rule == 'max') {
|
alert(msg);
|
}
|
if(status === -1){
|
alert('前端验证错误');
|
}
|
});
|
</pre>
|
<p>试下demo上传三个文件会出现弹出框提示</p>
|
<h3>手动触发验证</h3>
|
<p>有时我们需要额外调用验证方法,比如提交表单时验证下是不是有至少有一个文件上传。</p>
|
<p><input class="btn btn-primary" id="J_SubmitAuthDemo" value="验证是否上传了一个文件" type="button"></p>
|
<pre class='brush: js; '>
|
$('#J_SubmitAuthDemo').on('click', function (ev) {
|
var auth = uploader.get('auth');
|
var isPass = auth.testRequire();
|
if (isPass) {
|
alert('存在上传文件!');
|
}else{
|
alert('请至少上传一个文件!');
|
}
|
})
|
</pre>
|
<p>先要获取Auth实例,然后调用<code>testRequire()</code>方法。</p>
|
|
<p><code>testMax()</code>可以检验是否达到最大允许上传数。</p>
|
</div>
|
</div>
|
<h2 id="theme">使用不同的上传主题</h2>
|
|
<h3>示例</h3>
|
|
<p>以使用imageUploader(图片上传)主题为例</p>
|
<ul class="clearfix" id="J_ImageUploaderQueue">
|
<li>
|
<div id="J_UploadBg" class="unupload-area">
|
<a class="unupload" id="J_ImageUploaderBtn">
|
<span class="count"> 还可以上传<em id="J_UploadCount">5</em>图片! </span>
|
<s class="bg"></s>
|
</a>
|
</div>
|
</li>
|
</ul>
|
<div class="row">
|
<div class="span4">
|
<h3>主题html结构如下:</h3>
|
<pre class='brush: xml; '>
|
<ul class="clearfix" id="J_ImageUploaderQueue">
|
<li>
|
<div id="J_UploadBg" class="unupload-area">
|
<a class="unupload" id="J_ImageUploaderBtn">
|
<span class="count"> 还可以上传<em id="J_UploadCount">5</em>图片! </span>
|
<s class="bg"></s>
|
</a>
|
</div>
|
</li>
|
</ul>
|
</pre>
|
</div>
|
<div class="span8">
|
<h3>增加theme配置项</h3>
|
<pre class='brush: js; '>
|
new RenderUploader('#J_ImageUploaderBtn', '#J_ImageUploaderQueue', {
|
theme:"imageUploader",
|
urlsInputName:"imgUrlsInput",
|
serverConfig:{"action":"./upload.php", "data":{"iid":77010, "fieldId":132338}},
|
name:"Filedata",
|
authConfig:{
|
require:[true, "必须至少上传一个文件!"],
|
maxSize:[500, "文件大小为{size},文件太大!"],
|
allowExts:[
|
{"desc":"JPG,JPEG,PNG,GIF,BMP", "ext":"*.jpg;*.jpeg;*.png;*.gif;*.bmp"},
|
"文件格式错误!"
|
],
|
max:[5, "最多允许上传五张图片!"]
|
}
|
});
|
</pre>
|
<p><code>theme:"imageUploader"</code>使用uploader内置图片上传主题imageUploader,此主题会获取服务器返回的url,显示在页面。</p>
|
|
<p>imageUploader肯定无法100%满足实际的场景,这时候你可以制作自己的主题,请看<a href="http://www.36ria.com/5137" target="_blank">《如何制作属于自己的主题(上、下)》</a>,还可以监听uploader的事件做些额外的逻辑处理(但没办法覆盖主题的逻辑)。</p>
|
<div class="alert alert-info">如果自制主题,theme参数应该制定模块完整路径,比如<code>theme:"gallery/form/1.3/uploader/themes/imageUploader"</code>。</div>
|
<h3>如何自定义主题样式?</h3>
|
<div class="alert alert-info">使用主题时,会额外加载主题的style.css,由于是异步加载的,样式优先级会比较高。</div>
|
<p>不加载主题样式,可以如下处理</p>
|
<pre class='brush: js; '>
|
new RenderUploader('#J_ImageUploaderBtn', '#J_ImageUploaderQueue', {
|
theme:"imageUploader",
|
themeConfig:{
|
cssUrl:''
|
}
|
});
|
</pre>
|
<h3>如何改变主题的模板?</h3>
|
<pre class='brush: js; '>
|
new RenderUploader('#J_ImageUploaderBtn', '#J_ImageUploaderQueue', {
|
theme:"imageUploader",
|
themeConfig:{
|
fileTpl:
|
'<li id="queue-file-{id}" class="clearfix" data-name="{name}">' +
|
'<div class="tb-pic120">' +
|
'<a href="javascript:void(0);"><img class="J_Pic_{id}" src="" /></a>' +
|
'</div>' +
|
'<div class=" J_Mask_{id} pic-mask"></div>' +
|
'<div class="status-wrapper J_FileStatus">' +
|
'<div class="status waiting-status tips-upload-waiting"><p class="tips-text">等待上传,请稍候</p></div>' +
|
'<div class="status start-status progress-status success-status tips-uploading">' +
|
'<div class="J_ProgressBar_{id}"><s class="loading-icon"></s>上传中...</div>' +
|
'</div>' +
|
'<div class="status error-status tips-upload-error">' +
|
'<p class="J_ErrorMsg_{id} tips-text">上传失败,请重试!</p></div>' +
|
'</div>' +
|
'<a class="J_Del_{id} del-pic" href="#">删除</a>' +
|
'</li>'
|
}
|
});
|
</pre>
|
|
<div class="alert alert-info">欢迎大家提交自己的主题到uploader内。</div>
|
</div>
|
</div>
|
<h2 id="defaultData">默认数据展现</h2>
|
<p>在实际应用中通常会有个需求:用户已经上传了三张图片,然后保存,那么用户再进入这个页面时,应该如何展示这三张图片呢?</p>
|
<p>这里有个难点,我们需要把图片插入到组件的队列中,这样文件数的统计、删除等行为才是一致的。</p>
|
<h3>示例</h3>
|
<div class="row">
|
<div class="span4">
|
<script type="text/uploader-restore" id="J_UploaderRestore">
|
[
|
{
|
"name":"icon_evil.gif",
|
"size":1446,
|
"type":"image/gif",
|
"result":{
|
"status":1,
|
"data":{
|
"name":"icon_evil.gif",
|
"url":"http://tp4.sinaimg.cn/1653905027/50/5601547226/1",
|
"item_id":"42458"
|
}
|
}
|
}
|
]
|
</script>
|
<a id="J_RestoreUploaderBtn" class="g-u uploader-button" href="#"> 选择要上传的文件 </a>
|
<ul id="J_RestoreUploaderQueue" >
|
|
</ul>
|
<h3>服务器端在页面中打印如下数据:</h3>
|
<pre class='brush: js; '>
|
<script type="text/uploader-restore" id="J_UploaderRestore">
|
[
|
{
|
"name":"icon_evil.gif",
|
"size":1446,
|
"type":"image/gif",
|
"result":{
|
"status":1,
|
"data":{
|
"name":"icon_evil.gif",
|
"url":"http://tp4.sinaimg.cn/1653905027/50/5601547226/1",
|
"item_id":"42458"
|
}
|
}
|
}
|
]
|
</script>
|
</pre>
|
<p>为一个<code>array</code>,文件数据为<code>object</code>,结构跟队列中的file数据保持一致,所以看上去数据有些繁冗。</p>
|
</div>
|
<div class="span8">
|
<h3>初始化时增加restoreHook配置项</h3>
|
<pre class='brush: js; '>
|
new RenderUploader('#J_RestoreUploaderBtn', '#J_RestoreUploaderQueue', {
|
serverConfig:{ action:"upload.php" },
|
name:"Filedata",
|
urlsInputName:"fileUrls",
|
restoreHook:"#J_UploaderRestore"
|
});
|
</pre>
|
<p>好了,组件会自动将数据插入到queue中,并渲染出图片。</p>
|
</div>
|
</div>
|
|
<h2 id="button">button(按钮实例)控制</h2>
|
|
<div class="row">
|
<div class="span4">
|
<h3>示例</h3>
|
<a id="J_ButtonUploaderBtn" class="g-u uploader-button" href="#upload"> 选择要上传的文件 </a>
|
<ul id="J_ButtonUploaderQueue" >
|
|
</ul>
|
<div class="btn-wrapper">
|
</div>
|
<div class="control-group">
|
<div class="controls">
|
<label class="checkbox inline">
|
<input id="J_Disabled" name="disabled" type="checkbox" value="1" checked />
|
禁用按钮
|
</label>
|
<label class="checkbox inline">
|
<input id="J_Multiple" name="multiple" type="checkbox" value="1" />
|
开启多选
|
</label>
|
</div>
|
</div>
|
<p style="margin-top:10px;"> <input class="btn" id="J_UploadAll" type="button" value="上传所有等待的文件"></p>
|
</div>
|
<div class="span8">
|
<h3>初始化组件</h3>
|
<pre class='brush: js; '>
|
var ru = new RenderUploader('#J_ButtonUploaderBtn', '#J_ButtonUploaderQueue',{
|
serverConfig:{"action":"upload.php"},
|
name:"Filedata",
|
urlsInputName:"fileUrls",
|
autoUpload: false,
|
multiple:false,
|
disabled:true
|
});
|
</pre>
|
<h3>配置说明</h3>
|
<table class="table table-bordered table-striped">
|
<thead>
|
<tr>
|
<th style="width: 100px;">参数名</th>
|
<th style="width: 50px;">类型</th>
|
<th style="width: 100px;">默认值</th>
|
<th>描述</th>
|
</tr>
|
</thead>
|
<tbody>
|
<tr>
|
<td>autoUpload</td>
|
<td>Boolean</td>
|
<td>true</td>
|
<td>是否自动上传,当为<code>false</code>时,可以通过uploader的<code>upload()</code>和<code>uploadFiles()</code>手动上传队列中的文件。</td>
|
</tr>
|
<tr>
|
<td>multiple</td>
|
<td>Boolean</td>
|
<td>true</td>
|
<td>是否开启多选支持
|
<div class="alert alert-info">如果采用iframe上传,请设置为<code>false</code></div>
|
</td>
|
</tr>
|
<tr>
|
<td>disabled</td>
|
<td>Boolean</td>
|
<td>false</td>
|
<td>是否可用,false为按钮可用</td>
|
</tr>
|
</tbody>
|
</table>
|
<h3>通过设置uploader属性控制按钮</h3>
|
<pre class='brush: js; '>
|
//对组件的后续操作务必放在init事件内,因为组件时可能需要异步加载模板
|
ru.on("init", 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();
|
})
|
})
|
</pre>
|
<div class="alert alert-info"><strong>PS:</strong>对组件的后续操作务必放在<code>init</code>事件监听器内</div>
|
</div>
|
</div>
|
<h2 id="queue">queue(队列实例)控制</h2>
|
<div class="alert alert-info">queue的详细API请看<a href="http://www.36ria.com/demo/gal/gallery/form/1.3/doc/symbols/Queue.html" target="_blank">文档</a></div>
|
<div class="row">
|
<div class="span6">
|
<h3>示例</h3>
|
<a id="J_QueueUploaderBtn" class="g-u uploader-button" href="#"> 选择要上传的文件 </a>
|
<ul id="J_QueueUploaderQueue" >
|
|
</ul>
|
<p>想要操作队列,就必须先获取queue实例(为uploader的属性),比如下面的代码:</p>
|
<pre class='brush: js; '>
|
//uploaderQueueTest为RenderUploader的实例
|
uploaderQueueTest.on('init',function(ev){
|
var uploader = ev.uploader,
|
queue = uploader.get('queue');
|
})
|
</pre>
|
<p>下面举例说明常用的方法和属性。</p>
|
<h3>add():向队列添加文件</h3>
|
<p>
|
<input class="btn" id="J_Add" type="button" value="添加一个文件">
|
</p>
|
<pre class='brush: js; '>
|
$('#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);
|
});
|
</pre>
|
<h3>remove():删除队列中的文件</h3>
|
<p>
|
<input class="btn" id="J_DelFirst" type="button" value="删除第一个文件">
|
</p>
|
<pre class='brush: js; '>
|
$('#J_DelFirst').on('click', function (ev) {
|
var removeFile = queue.remove(0);
|
S.log('删除的文件数据为:'+removeFile);
|
});
|
</pre>
|
<div class="alert alert-info">留意remove()的参数可以是队列数组的索引,比如上面代码的0,是取队列第一个文件数据;也可以是文件的id(唯一),比如remove('file-26')</div>
|
<h3>fileStatus(index, status, args):改变文件状态</h3>
|
<p>默认的主题共有以下文件状态:'waiting'、'start'、'progress'、'success'、'cancel'、'error'</p>
|
<p>不同的主题拥有的状态情况可能存在差异。</p>
|
<p>
|
<input class="btn" id="J_ChangeStatus" type="button" value="改变第一个文件状态为success">
|
</p>
|
<pre class='brush: js; '>
|
$('#J_ChangeStatus').on('click', function (ev) {
|
queue.fileStatus(0, 'success');
|
});
|
</pre>
|
<h3>clear():删除队列内的所有文件</h3>
|
<p>
|
<input class="btn" id="J_Clear" type="button" value="删除所有文件">
|
</p>
|
<pre class='brush: js; '>
|
$('#J_Clear').on('click', function (ev) {
|
queue.clear();
|
});
|
</pre>
|
|
</div>
|
<div class="span6">
|
<h3>files:通过该属性可以获取队列中所有的文件数据</h3>
|
<p>
|
<input class="btn" id="J_GetAll" type="button" value="获取所有文件id">
|
</p>
|
<pre class='brush: js; '>
|
$('#J_GetAll').on('click', function (ev) {
|
var ids = [],
|
files = queue.get('files');
|
S.each(files, function (file) {
|
ids.push(file.id);
|
});
|
alert('所有文件id:' + ids);
|
});
|
</pre>
|
<h3>getFiles(type):获取指定状态下的文件</h3>
|
<p>
|
<input class="btn" id="J_GetStatusFileIds" type="button" value="获取所有等待状态的文件id">
|
</p>
|
<pre class='brush: js; '>
|
$('#J_GetStatusFileIds').on('click', function (ev) {
|
var files = queue.getFiles('waiting'),
|
ids = [];
|
S.each(files, function (file) {
|
ids.push(file.id);
|
});
|
alert('所有等待中的文件id为:' + ids);
|
});
|
</pre>
|
<h3>getIndexs(type):获取等指定状态的文件对应的文件数组索引值组成的数组</h3>
|
<p>getFiles()和getFileIds()的作用是不同的,getFiles()类似过滤数组,获取的是指定状态的文件数据,而getFileIds()只是获取指定状态下的文件对应的在文件数组内的索引值。</p>
|
<p>
|
<input class="btn" id="J_GetStatusFilesIndex" type="button" value="获取所有等待状态文件index">
|
</p>
|
<pre class='brush: js; '>
|
$('#J_GetStatusFilesIndex').on('click', function () {
|
var indexs = queue.getIndexs('waiting');
|
alert('所有等待中的文件index为:' + indexs);
|
})
|
</pre>
|
</div>
|
</div>
|
<h2 id="api">uploader常用接口</h2>
|
<div class="alert alert-info">uploader的详细API请看<a href="http://www.36ria.com/demo/gal/gallery/form/1.3/doc/symbols/Uploader.html" target="_blank">文档</a></div>
|
<h3>uploader常用属性/配置</h3>
|
<p>uploader的配置都会写入成uploader的属性内。uploader的几个关键配置前面都有提到了,这里做个汇总。</p>
|
<table class="table table-bordered table-striped">
|
<thead>
|
<tr>
|
<th style="width: 100px;">属性名</th>
|
<th style="width: 50px;">类型</th>
|
<th style="width: 100px;">默认值</th>
|
<th style="width: 50px;">是否只读</th>
|
<th>描述</th>
|
</tr>
|
</thead>
|
<tbody>
|
<tr>
|
<td>type</td>
|
<td>String|Array</td>
|
<td>"auto"</td>
|
<td>只读</td>
|
<td>采用的上传方案,当值是数组时,比如“type” : ["flash","ajax","iframe"],按顺序获取浏览器支持的方式,该配置会优先使用flash上传方式,如果浏览器不支持flash,会降级为ajax,如果还不支持ajax,会降级为iframe;当值是字符串时,比如“type” : “ajax”,表示只使用ajax上传方式。这种方式比较极端,在不支持ajax上传方式的浏览器会不可用;
|
<div class="alert alert-info">当“type” : “auto”,auto是一种特例,等价于["ajax","flash","iframe"]。</div>
|
<div class="alert alert-error">不再推荐配置type,除非在使用flash时遇到难以解决的问题。</div>
|
</td>
|
</tr>
|
<tr>
|
<td>curUploadIndex</td>
|
<td>Number</td>
|
<td>""</td>
|
<td>只读</td>
|
<td>
|
当前上传的文件对应的在数组内的索引值,如果没有文件正在上传,值为空
|
</td>
|
</tr>
|
<tr>
|
<td>isAllowUpload</td>
|
<td>Boolean</td>
|
<td>true</td>
|
<td>只读</td>
|
<td>
|
是否允许上传文件
|
</td>
|
</tr>
|
<tr>
|
<td>isAllowUpload</td>
|
<td>Boolean</td>
|
<td>true</td>
|
<td>读/写</td>
|
<td>
|
是否允许上传文件,当文件正在上传时,isAllowUpload为false
|
</td>
|
</tr>
|
<tr>
|
<td>queue</td>
|
<td>Queue</td>
|
<td>''</td>
|
<td>只读</td>
|
<td>
|
Queue队列的实例,想要对队列进行操作或监听队列的事件,就必须先获取这个属性
|
</td>
|
</tr>
|
<tr>
|
<td>restoreHook</td>
|
<td>String</td>
|
<td>''</td>
|
<td>只读</td>
|
<td>
|
已经存在的文件数据待提取的容器钩子,用法请看<a href="#defaultData">默认数据展现</a>
|
</td>
|
</tr>
|
<tr>
|
<td>autoUpload</td>
|
<td>Boolean</td>
|
<td>true</td>
|
<td>读/写</td>
|
<td>是否自动上传,当为<code>false</code>时,可以通过uploader的<code>upload()</code>和<code>uploadFiles()</code>手动上传队列中的文件。</td>
|
</tr>
|
<tr>
|
<td>multiple</td>
|
<td>Boolean</td>
|
<td>true</td>
|
<td>读/写</td>
|
<td>是否开启多选支持
|
<div class="alert alert-info">如果采用iframe上传,请设置为<code>false</code></div>
|
</td>
|
</tr>
|
<tr>
|
<td>multipleLen</td>
|
<td>Number</td>
|
<td>-1</td>
|
<td>读/写</td>
|
<td>用于限制多选文件个数,值为负时不设置多选限制(v1.2.6+)
|
</td>
|
</tr>
|
<tr>
|
<td>disabled</td>
|
<td>Boolean</td>
|
<td>false</td>
|
<td>读/写</td>
|
<td>是否可用,false为按钮可用</td>
|
</tr>
|
<tr>
|
<td>serverConfig</td>
|
<td>Object</td>
|
<td>{action:'', data:{}, dataType:'json'}</td>
|
<td>读/写</td>
|
<td>服务器端配置,包括最重要的<code>action</code>(路径)配置,<code>data</code>为post到服务器端数据
|
</td>
|
</tr>
|
<tr>
|
<td>data</td>
|
<td>Object</td>
|
<td>{}</td>
|
<td>读/写</td>
|
<td>此配置用于动态修改post给服务器的数据,会覆盖serverConfig的data配置(v1.2.6+)
|
</td>
|
</tr>
|
<tr>
|
<td>name</td>
|
<td>String</td>
|
<td>Filedata</td>
|
<td>只读</td>
|
<td>文件上传域name名,组件会根据这个name值生成一个文件上传input(type="file")
|
</td>
|
</tr>
|
<tr>
|
<td>urlsInputName</td>
|
<td>String</td>
|
<td>''</td>
|
<td>只读</td>
|
<td>用于存放服务器端返回的文件路径的input(type="hidden")
|
</td>
|
</tr>
|
</tbody>
|
</table>
|
<div class="row">
|
<div class="span6">
|
<h3>uploader常用方法</h3>
|
<h4>upload (index)</h4>
|
<p>上传指定队列索引的文件。</p>
|
<pre class='brush: js; '>
|
//上传队列中的第一个文件,uploader为Uploader的实例
|
uploader.upload(0)
|
</pre>
|
<h4>uploadFiles (status)</h4>
|
<p>批量上传队列中的指定状态下的文件。</p>
|
<pre class='brush: js; '>
|
//上传队列中所有等待的文件
|
uploader.uploadFiles("waiting")
|
</pre>
|
<h4>cancel (index)</h4>
|
<p>取消文件上传,当index参数不存在时取消当前正在上传的文件的上传。cancel并不会停止其他文件的上传(对应方法是stop)。</p>
|
<pre class='brush: js; '>
|
//取消当前正在上传的文件的上传
|
uploader.cancel();
|
</pre>
|
<h4>stop()</h4>
|
<p>停止上传动作</p>
|
<pre class='brush: js; '>
|
//停止上传
|
uploader.stop();
|
</pre>
|
</div>
|
<div class="span6">
|
<h3>uploader常用事件</h3>
|
<table class="table table-bordered table-striped">
|
<thead>
|
<tr>
|
<th style="width: 100px;">事件名</th>
|
<th>描述</th>
|
</tr>
|
</thead>
|
<tbody>
|
<tr>
|
<td>select </td>
|
<td>选择完文件后触发</td>
|
</tr>
|
<tr>
|
<td>start </td>
|
<td>开始上传后触发</td>
|
</tr>
|
<tr>
|
<td>progress </td>
|
<td>正在上传中时触发,这个事件在iframe上传方式中不存在</td>
|
</tr>
|
<tr>
|
<td>success </td>
|
<td>上传成功后触发</td>
|
</tr>
|
<tr>
|
<td>error </td>
|
<td>上传失败后触发</td>
|
</tr>
|
<tr>
|
<td>cancel </td>
|
<td>取消上传后触发</td>
|
</tr>
|
</tbody>
|
</table>
|
</div>
|
</div>
|
<h2 id="plugins">关于插件</h2>
|
|
</div>
|
</div>
|
<script>
|
var S = KISSY,
|
//包路径,实际使用请直接配置为"http://a.tbcdn.cn/s/kissy/"
|
path = S.Config.debug && "../../../../../../" || "http://a.tbcdn.cn/s/kissy/",
|
$ = S.Node.all;
|
S.config({
|
packages:[
|
{
|
name:"gallery",
|
path:path,
|
charset:"utf-8"
|
}
|
]
|
});
|
KISSY.use('gallery/form/1.3/uploader/index', function (S, RenderUploader) {
|
new RenderUploader('#J_UploaderBtn', '#J_UploaderQueue', {
|
//服务器端配置
|
serverConfig:{
|
//处理上传的服务器端脚本路径
|
action:"upload.php"
|
},
|
// 文件域
|
name:"Filedata",
|
//用于放服务器端返回的url的隐藏域
|
urlsInputName:"fileUrls"
|
});
|
|
var authDemo = new RenderUploader('#J_UploaderAuthBtn', '#J_UploaderAuthQueue', {
|
serverConfig:{ action:"upload.php" },
|
name:"Filedata",
|
urlsInputName:"fileUrls",
|
//验证配置
|
authConfig:{
|
require:[true, "必须至少上传一个文件!"],
|
max:[3, "最多上传{max}个文件!"],
|
maxSize:[1000, "文件大小为{size},文件太大!"],
|
allowRepeat:[false, "该文件已经存在!"],
|
allowExts:[
|
{"desc":"JPG,JPEG,PNG,GIF,BMP", "ext":"*.jpg;*.jpeg;*.png;*.gif;*.bmp"},
|
"不支持{ext}格式的文件上传!"
|
]
|
}
|
});
|
authDemo.on('init',function(ev){
|
var uploader = ev.uploader;
|
uploader.on('error', function (ev) {
|
var rule = ev.rule, msg = ev.msg,status = ev.status;
|
if (rule == 'max') {
|
alert(msg);
|
}
|
if(status === -1){
|
alert('前端验证错误');
|
}
|
});
|
$('#J_SubmitAuthDemo').on('click', function (ev) {
|
var auth = uploader.get('auth');
|
var isPass = auth.testRequire();
|
if (isPass) {
|
alert('存在上传文件!');
|
}else{
|
alert('请至少上传一个文件!');
|
}
|
})
|
});
|
|
new RenderUploader('#J_ImageUploaderBtn', '#J_ImageUploaderQueue', {
|
theme:"imageUploader",
|
urlsInputName:"imgUrlsInput",
|
serverConfig:{"action":"./upload.php", "data":{"iid":77010, "fieldId":132338}},
|
name:"Filedata",
|
authConfig:{
|
require:[true, "必须至少上传一个文件!"],
|
maxSize:[500, "文件大小为{size},文件太大!"],
|
allowExts:[
|
{"desc":"JPG,JPEG,PNG,GIF,BMP", "ext":"*.jpg;*.jpeg;*.png;*.gif;*.bmp"},
|
"文件格式错误!"
|
],
|
max:[5, "最多允许上传五张图片!"]
|
}
|
});
|
|
new RenderUploader('#J_RestoreUploaderBtn', '#J_RestoreUploaderQueue', {
|
serverConfig:{ action:"upload.php" },
|
name:"Filedata",
|
urlsInputName:"fileUrls",
|
restoreHook:"#J_UploaderRestore"
|
});
|
|
var ru = new RenderUploader('#J_ButtonUploaderBtn', '#J_ButtonUploaderQueue',{
|
serverConfig:{"action":"upload.php"},
|
name:"Filedata",
|
urlsInputName:"fileUrls",
|
autoUpload: false,
|
multiple:false,
|
disabled:true
|
});
|
//对组件的后续操作务必放在init事件内,因为组件时可能需要异步加载模板
|
ru.on("init", 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();
|
})
|
});
|
|
var uploaderQueueTest = new RenderUploader('#J_QueueUploaderBtn', '#J_QueueUploaderQueue',{
|
serverConfig:{"action":"upload.php"},
|
name:"Filedata",
|
urlsInputName:"fileUrls"
|
});
|
uploaderQueueTest.on('init',function(ev){
|
var uploader = ev.uploader,
|
queue = uploader.get('queue');
|
$('#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);
|
});
|
$('#J_DelFirst').on('click', function (ev) {
|
var removeFile = queue.remove(0);
|
S.log('删除的文件数据为:'+removeFile);
|
});
|
$('#J_Clear').on('click', function (ev) {
|
queue.clear();
|
});
|
$('#J_GetAll').on('click', function (ev) {
|
var ids = [],
|
files = queue.get('files');
|
S.each(files, function (file) {
|
ids.push(file.id);
|
});
|
alert('所有文件id:' + ids);
|
});
|
$('#J_ChangeStatus').on('click', function (ev) {
|
queue.fileStatus(0, 'success');
|
});
|
$('#J_GetStatusFileIds').on('click', function (ev) {
|
var files = queue.getFiles('waiting'),
|
ids = [];
|
S.each(files, function (file) {
|
ids.push(file.id);
|
});
|
alert('所有等待中的文件id为:' + ids);
|
});
|
$('#J_GetStatusFilesIndex').on('click', function () {
|
var indexs = queue.getIndexs('waiting');
|
alert('所有等待中的文件index为:' + indexs);
|
})
|
});
|
})
|
</script>
|
|
<div id="footer">
|
© Copyright 2012-2012, KF小组.
|
</div>
|
<!-- 代码高亮 START -->
|
<link href='../../assets/syntaxhighlighter_3.0.83/sh.css' rel='stylesheet'
|
type='text/css'/>
|
<script type="text/javascript"
|
src="../../assets/syntaxhighlighter_3.0.83/sh.js"></script>
|
<script type="text/javascript">SyntaxHighlighter.all();</script>
|
<!-- 代码高亮 END -->
|
</body>
|
</html>
|