swfupload 2.2 文件最大上传个数的重编译
项目中用到了swfupload 2.2 ,并且有一个需求,就是在上传个数限定的条件下上传文件后可以有一个删除操作,由此我们遇到了问题 ,虽然 file_upload_limit 参数可以控制文件上传总数,但是js在执行删除时,flash内部的参数没有更改,file_upload_limit代表的是文件成功的个数,而不是我 们想要的(如果我的问题你还没有明白,比如 我们将file_upload_limit 设为5 ,我们现在成功上传3张,用js 删除其中2张,那么我们现在html中还有一张图片,我们还可以上传2张图片,而不是4张,而我们想要的结果是用户最大可以上传5张,现在用户可能一张也 保存不了)。 swfupload 内部的文件个数统计是由flash完成的,我翻看了swfupload.js(我看的是2.5版,并做了些注释,文章下方提供下载),证实js对此无能为力。为此我这个as 初学者不得不对swfload.swf进行一点修改。多亏swfupload是开源的,我们可以在google code 下载到 源码,源码中没有提供fla文件,我使用SWFDecompiler 对 2.5版进行反编译的时候发现SWFDecompiler 5.6和5.5 在还没有完成的时候就会崩溃掉,而swfupload 2.2则没有这种问题。而项目中用到的正是2.2 ,不用我操心了。
2.2版中的fla文件没有什么稀奇,就是一个300 px * 300 px(右击画布在 “文档属性”中设置 ) 的新建文件引入了 swfupload.as (看来反编译都是白费劲了).
为了添加删除操作我们要对handlers.js (位于 swfupload demo版applicationdemo 文件夹 )做一点修改 ,我们使用了jQuery 对addImage 函数进行了修改。
function addImage(src,touxiang) { var newImg = document.createElement("img"); newImg.style.margin = "5px"; var $licon=$('<li><p class="p_box"><span><a href="#">删除</a></span><input type="radio">默认显示</p><p><input type="text" name=""></p></li>') $licon.prepend($(newImg)); document.getElementById("thumbnails").appendChild($licon.get(0)); if (newImg.filters) { try { newImg.filters.item("DXImageTransform.Microsoft.Alpha").opacity = 0; } catch (e) { // If it is not set initially, the browser will throw an error. This will set it if it is not set yet. newImg.style.filter = 'progid:DXImageTransform.Microsoft.Alpha(opacity=' + 0 + ')'; } } else { newImg.style.opacity = 0; } newImg.onload = function () { fadeIn(newImg, 0); }; newImg.src = src; }
这是文档结构的,我们还要添加删除操作。
$('.p_box ').live('click',function(e){ $(this).parents('li').remove(); e.preventDefault(); });
那么剩下的就是as的事了,如何使用js 控制flash文件上传个数那?
在swfupload.js中我看到了 callFlash 方法:
SWFUpload.prototype.callFlash = function (functionName, argumentArray) { argumentArray = argumentArray || []; var movieElement = this.getMovieElement(); var returnValue, returnString; // Flash's method if calling ExternalInterface methods (code adapted from MooTools). try { returnString = movieElement.CallFunction('<invoke name="' + functionName + '" returntype="javascript">' + __flash__argumentsToXML(argumentArray, 0) + '</invoke>'); returnValue = eval(returnString); } catch (ex) { throw "Call to " + functionName + " failed"; } // Unescape file post param values if (returnValue != undefined &amp;&amp; typeof returnValue.post === "object") { returnValue = this.unescapeFilePostParams(returnValue); } return returnValue; };
它使用了如下的方法向flash中传递参数。
movieElement.CallFunction('<invoke name="' + functionName + '" returntype="javascript">' + __flash__argumentsToXML(argumentArray, 0) + '</invoke>');
具体的原理也不知道,CallFunction和invoke 的介绍网上好像不是太多。
知道了如何传递参数那么我们就可以仿照着写一个函数,我们称为minusNum
SWFUpload.prototype.minusNum = function () { this.callFlash("minusNum"); };
swfupload.as 和swfupload.js中定义的函数基本是一一对于的, 这个函数的意思就是要要flash执行minusNum方法。
下面该干什么那,当然是寻找as中控制上传个数的参数并进行修改了。在尝试了,remaining_uploads和 queue_slots_remaining 后终于找到了真的的参数 successful_uploads 。由于他已经是全局变量,不需要我们修改了,我们要做的是添加方法,在每次js删除操作时减小它的值。
在SetupExternalInterface 中添加
ExternalInterface.addCallback("minusNum", this.minusNum);
在合适的地方添加方法
private function minusNum():void{ if(this.successful_uploads>0){ this.successful_uploads--; } }
好的这样只要我们每次删除时执行一次minusNum方法就可以了,假设我们实例化swfupload为swfu,上方删除操作的代码可以改为:
$('.p_box a').live('click',function(e){ $(this).parents('li').remove(); swfu.minusNum() e.preventDefault(); });