Flex多图片压缩上传
前段时间按照公司要求做了一个Flex多图片压缩上传组件,使网站实现了图片的快速上传与分享,提高了用户体验。 使用Flex4开发,Flex好像没有自带的多线程功能,因此借用了?开源项目async-threading实现多线程并发上传。 google code地址:http://code.google.com/p/async-threading/ 要在flex4 sdk环境下使用,要先修改一下源代码,打开com.symantec.premiumServices.asyncThreading.handlers.FPSObserverHandler
首先自定义一个?CommendThread.as
package?common { import?com.symantec.premiumServices.asyncThreading.abstract.AbstractAsyncThread; import?com.symantec.premiumServices.asyncThreading.interfaces.IAsyncThreadResponder; public?class?CommendThread?extends?AbstractAsyncThread?implements?IAsyncThreadResponder { private?var?_f:Function; public?function?CommendThread(f:Function) { this._f?=?f; } public?function?execute():void { _f.call(); this.kill(); } } } 定义图片组件?MyImage.mxml
<?xml?version="1.0"?encoding="utf-8"?> <s:ItemRenderer?xmlns:fx="http://ns.adobe.com/mxml/2009"? xmlns:s="library://ns.adobe.com/flex/spark"? xmlns:mx="library://ns.adobe.com/flex/mx"? autoDrawBackground="true"> <fx:Script> <![CDATA[ import?mx.controls.Alert; ]]> </fx:Script> <s:Image?width="100"?height="100"> <s:creationComplete> <![CDATA[ var?img:Image?=?event.target?as?Image; var?file:FileReference?=?data?as?FileReference; img.source?=?file.data; ]]> </s:creationComplete> </s:Image> <s:Image?x="84"?y="0"?width="16"?height="15"?source="@Embed('close_btn.png')"> <s:click> <![CDATA[ parentDocument.valiUpload(); var?file:FileReference?=?data?as?FileReference; parentDocument.removeImageArray(file);? ]]> </s:click> <s:mouSEOver> <![CDATA[ Mouse.cursor?=?MouseCursor.BUTTON; ]]> </s:mouSEOver> <s:mouSEOut> <![CDATA[ Mouse.cursor?=?MouseCursor.ARROW; ]]> </s:mouSEOut> </s:Image> </s:ItemRenderer> 主文件?flexMultiUpload.mxml
<?xml?version="1.0"?encoding="utf-8"?> <s:Application?xmlns:fx="http://ns.adobe.com/mxml/2009" ???xmlns:s="library://ns.adobe.com/flex/spark" ???xmlns:mx="library://ns.adobe.com/flex/mx" ???width="700"?height="450"?minWidth="955"?minHeight="600"?initialize="init()"> <fx:Style> @namespace?s?"library://ns.adobe.com/flex/spark"; @namespace?mx?"library://ns.adobe.com/flex/mx"; .back { backgroundColor:#E7E7E7; borderAlpha:0; } </fx:Style> <fx:Script> <![CDATA[ import?common.CommendThread; import?mx.collections.ArrayCollection; import?mx.controls.Alert; import?mx.graphics.codec.JPEGEncoder; import?mx.utils.StringUtil; import?spark.components.Image; private?var?fileRef:FileReferenceList?=?new?FileReferenceList(); [Bindable] private?var?imageArray:ArrayCollection?=?new?ArrayCollection;//图片数组 private?var?imageNameArray:ArrayCollection?=?new?ArrayCollection;//上传图片名称数组 private?var?uploadURL:String?=?"http://www.leku.com/flex/flexuploadimage?"; private?var?header:URLRequestHeader?=?new?URLRequestHeader("Content-type",?"application/octet-stream"); private?var?isUploading:Boolean?=?false; //初始化 public?function?init():void { //初始化图片上传的url var?url:String?=?this.parameters.url; if(url?!=?null?&&?url.length>0) { uploadURL?=?decodeURI(this.parameters.url); } //初始化文件选择事件 fileRef.addEventListener(Event.SELECT,selectFileHandler); fileRef.addEventListener(Event.COMPLETE,completeFileHandler); } public?function?valiUpload():void { if(isUploading) { Alert.show("正在上传中,请稍后操作。"); throw?new?Error("正在上传中,请稍后操作。"); } } //打开图片选择框 private?function?showSelectDialog():void { valiUpload(); fileRef.browse([ new?FileFilter("Images?(*.jpg,?*.jpeg,?*.gif,?*.png)",?"*.jpg;*.jpeg;*.gif;*.png") ]); } //图片选择完成后 private?function?selectFileHandler(e:Event):void { for?each?(var?file:FileReference?in?fileRef.fileList)? { if(imageNameArray.contains(file.name)) { continue; } file.load(); file.addEventListener(Event.COMPLETE,completeFileHandler); } uploadButton.visible?=?true; } //图片加载完成后 private?function?completeFileHandler(e:Event):void { var?file:FileReference?=?e.target?as?FileReference; insertImageArray(file); } //图片数组增加元素 private?function?insertImageArray(file:FileReference):void { imageArray.addItem(file); imageNameArray.addItem(file.name); } //删除图片数组元素 public?function?removeImageArray(file:FileReference):void { var?index:Number?=?imageArray.getItemIndex(file); if(index?>=?0) { imageArray.removeItemAt(index); } index?=?imageNameArray.getItemIndex(file.name); if(index?>=?0) { imageNameArray.removeItemAt(index); } } private?var?value:Number?=?0; private?var?total:Number?=?0; private?var?index:Number?=?0; private?var?maxSize:Number?=?1024;//设置图片压缩尺寸 //上传图片 private?function?upload():void { if(imageArray.length?<=?0) { Alert.show("请选择图片"); return; } valiUpload(); isUploading?=?true; value?=?0; total?=?imageArray.length; progressBar.visible?=?true; progressBar.setProgress(value,total); for?each?(var?file:FileReference?in?imageArray)? { uploading(file); } } private?function?uploading(file:FileReference):void { new?CommendThread(function():void { var?fileName:String?=?file.name; var?loader:Loader?=?new?Loader(); loader.contentLoaderInfo.addEventListener(Event.COMPLETE,?function():void { var?bm:Bitmap=loader.content?as?Bitmap; var?bmd:BitmapData; if((bm.width>=bm.height)&&bm.width>maxSize) { var?rateW:Number=maxSize/bm.width; var?h:Number=rateW*bm.height; bmd=new?BitmapData(maxSize,h,true,0); bmd.draw(bm.bitmapData,new?Matrix(rateW,rateW),null,true); bm=new?Bitmap(bmd,PixelSnapping.ALWAYS,true); bmd?=?bm.bitmapData; } else?if(bm.height>bm.width&&bm.height>maxSize) { var?rateH:Number=maxSize/bm.height; var?w:Number=rateH*bm.width; bmd=new?BitmapData(w,maxSize,new?Matrix(rateH,rateH),true); bmd?=?bm.bitmapData; } else { bmd?=?bm.bitmapData; } var?urlLoader:URLLoader?=?new?URLLoader(); var?jpeg:JPEGEncoder?=?new?JPEGEncoder(80); var?b:ByteArray?=?jpeg.encode(bmd); var?subRequest:URLRequest?=?new?URLRequest(); subRequest.method?=?URLRequestMethod.POST; subRequest.requestHeaders.push(header); subRequest.url?=?uploadURL+"&fileName="+encodeURI(fileName==null?"":fileName);//url编码,不然汉字会乱码 subRequest.data?=?b; urlLoader.load(subRequest);?? urlLoader.addEventListener(Event.COMPLETE,function(e:Event):void{ progressBar.setProgress(++value,total); ExternalInterface.call("flexCallBack",urlLoader.data); if(value?==?total) { imageArray.removeAll(); imageNameArray.removeAll(); value?=?0; total?=?0; progressBar.visible?=?false; ExternalInterface.call("flexCompleteCallBack"); isUploading?=?false; } // System.gc(); }); }); loader.loadBytes(file.data); }).start(); } ]]> </fx:Script> <s:VGroup?x="0"?y="0"?width="700"?height="450"?gap="0"> <s:HGroup?width="700"?height="400"?gap="0"> <s:Scroller> <s:DataGroup?width="684"?height="400"?dataProvider="{imageArray}" ?focusColor="#EE7091"?itemRenderer="mycomponent.MyImage"> <s:layout> <s:TileLayout?useVirtualLayout="true"??requestedColumnCount="6"> </s:TileLayout> </s:layout> </s:DataGroup> </s:Scroller> </s:HGroup> <s:BorderContainer?width="700"?height="50"??styleName="back"> <s:Button?x="210"?y="8"?width="116"?height="35"?label="选择图片"?click="showSelectDialog()"> <s:mouSEOver> <![CDATA[ Mouse.cursor?=?MouseCursor.BUTTON; ]]> </s:mouSEOver> <s:mouSEOut> <![CDATA[ Mouse.cursor?=?MouseCursor.ARROW; ]]> </s:mouSEOut> </s:Button> <s:Button?x="370"?y="8"?width="116"?height="35"?label="图片上传"??click="upload()"?id="uploadButton"?visible="false"> <s:mouSEOver> <![CDATA[ Mouse.cursor?=?MouseCursor.BUTTON; ]]> </s:mouSEOver> <s:mouSEOut> <![CDATA[ Mouse.cursor?=?MouseCursor.ARROW; ]]> </s:mouSEOut> </s:Button> </s:BorderContainer> </s:VGroup> <mx:ProgressBar?x="150"?y="200"?width="400"?id="progressBar"?mode="manual"?labelPlacement="center"?label="%1?of?%2,总进度:%3%%"?visible="false"> </mx:ProgressBar> </s:Application> 以下是工程结构
这是close_btn.png的图片: ?
接下来就是要导出swf文件了,如果方式不对的话,会导致文件很大,从何造成网页组件加载很慢。 我是用的是flash builder开发,流程如下 右键点击工程-->选择Properties -->选择 Flex Build Path-->选择RSL选择,这样编译的时候只会加载使用到的类库,大大 降低swf文件大小-->点击OK
点击Export Release Build
选择工程,然后点击finish,完成后在bin-release目录下找到flexMultiUpload.swf
可以使用浏览器直接打开,或者flash客户端(尽量把flash更新到最新版本) 服务端使用java struts2
import?java.io.File; import?java.io.InputStream; import?javax.servlet.http.HttpServletRequest; import?javax.servlet.http.HttpServletResponse; import?org.apache.commons.io.FileUtils; import?org.apache.struts2.ServletActionContext; import?org.apache.struts2.convention.annotation.Action; import?com.opensymphony.xwork2.ActionSupport; public?class?FlexAction??extends?ActionSupport{ /** ?*? ?*/ private?static?final?long?serialVersionUID?=?-3543364166243030722L; private?HttpServletRequest?request?=?ServletActionContext.getRequest(); private?HttpServletResponse?response?=?ServletActionContext.getResponse(); public?static?final?Integer?MAX_SIZE?=?1024*1024*2;//允许图片最大尺寸 private?String?fileName; @Action(value?=?"flexuploadimage") public?String?upload()?throws?Exception{ InputStream?inputStream?=?request.getInputStream(); int?formlength?=?request.getContentLength(); //如果图片大于允许的值 if(formlength?>?MAX_SIZE){ //返回异常信息 response.getOutputStream().println("自定义返回信息,或者跳转到异常页面"); return?null; } byte[]?formcontent?=?new?byte[formlength]; int?totalread?=?0; int?nowread?=?0; while?(totalread?<?formlength)?{ nowread?=?inputStream.read(formcontent,?totalread,?formlength); totalread?+=?nowread; } //将图片写入本地或者图片服务器 File?file?=?new?File("D:/flex",?fileName); FileUtils.writeByteArrayToFile(file,?formcontent); return?null; } public?String?getFileName()?{ return?fileName; } public?void?setFileName(String?fileName)?{ this.fileName?=?fileName; } } jsp页面调用 <%@page?import="java.net.URLEncoder"%> <%@?page?language="java"?contentType="text/html;?charset=UTF-8"?pageEncoding="UTF-8"%> <%@?taglib?prefix="c"?uri="http://java.sun.com/jsp/jstl/core"?%> <%@?taglib?prefix="fmt"?uri="http://java.sun.com/jsp/jstl/fmt"?%> <%@?taglib?prefix="fn"?uri="http://java.sun.com/jsp/jstl/functions"?%> <% request.setAttribute("url",?URLEncoder.encode("上传路径",?"utf-8")); %> <div?style="height:600px;width:800px;display:table-cell;vertical-align:middle;text-align:center;"> <embed?src="flexMultiUpload.swf"?style="height:450px;width:700px;border:?#C9DDEA?solid?1px;vertical-align:?middle;"?flashVars="url=${url?}"?allowScriptAccess="always"> <br/> <div?style="margin-left:?-450px;margin-top:?10px;"> <span>如果不能正常使用,请将Flash升级到最新版本。</span> </div> </div> 组件缺陷(由于本文作者偷懒的结果,哈哈): 每一个图片新开一个线程并发上传,如果用户一次性上传的图片过多,可能会造成客户端挂掉的现象。 解决办法:(1)限制每次上传的图片数量 (2)做一个上传队列,几个线程并发执行队列中的任务(可以参考QQ空间相册普通上传功能,注意:不是极速上传)。 (3)flex的多线程是借助于第三方的 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |