`
windmark
  • 浏览: 32156 次
社区版块
存档分类
最新评论

Flex 多图片压缩上传

    博客分类:
  • Flex
 
阅读更多

转自:http://my.oschina.net/eatsuger/blog/85893

 

前段时间按照公司要求做了一个Flex多图片压缩上传组件,使网站实现了图片的快速上传与分享,提高了用户体验。

使用Flex4开发,Flex好像没有自带的多线程功能,因此借用了 开源项目async-threading实现多线程并发上传。

google code地址:http://code.google.com/p/async-threading/

要在flex4 sdk环境下使用,要先修改一下源代码,打开com.symantec.premiumServices.asyncThreading.handlers.FPSObserverHandler


将import mx.core.Application; 修改为import spark.components.Application;


将private var _appRef:Application = Application.applicationas Application;修改为private var _appRef:Application = FlexGlobals.topLevelApplication as Application;


同时导入import mx.core.FlexGlobals;
        这个api要求自定义的线程继承AbstractAsyncThread然后实现IAsyncThreadResponder接口。

首先自定义一个 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,0,0,rateW),null,null,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,true,0);
							bmd.draw(bm.bitmapData,new Matrix(rateH,0,0,rateH),null,null,null,true);
							bm=new Bitmap(bmd,PixelSnapping.ALWAYS,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的多线程是借助于第三方的

 

分享到:
评论

相关推荐

    Flex 图片压缩、上传

    这篇博文“Flex 图片压缩、上传”可能探讨了如何在Flex环境中实现图片的压缩和上传功能。 首先,我们需要理解Flex中的图像处理基础。在Flex中,我们可以使用BitmapData类来代表图像数据。BitmapData对象可以从本地...

    图片压缩flex demo

    "图片压缩flex demo"这个项目显然关注的是使用Flex技术进行图片压缩的示例。Flex是一种基于Adobe Flash Player或Adobe AIR运行时的开放源代码框架,用于构建富互联网应用程序(RIA)。它允许开发者使用ActionScript ...

    图片客户端压缩上传项目源码

    图片浏览器端压缩上传,flex技术实现图片浏览器端压缩上传

    flex自定义截取图片上传

    本项目“flex自定义截取图片上传”就是这样一个解决方案,它采用Adobe Flex技术实现,结合C#后端处理,为用户提供了一套完整的截图上传系统。以下是关于这个项目的详细知识点: 1. **Flex技术**:Flex是Adobe公司...

    Flex 测试项目,图片压缩、上传、图片裁剪,Module测试,国际化

    “图片压缩、上传、图片裁剪”是项目中的功能模块,这表明该Flex应用提供了图像处理服务。图片压缩可能涉及算法优化,减少图像文件大小以提高网页加载速度或节省存储空间。图片上传则涉及到前端与后端的交互,用户...

    flex图片上传带预览功能_flexsc.zip

    标题"flex图片上传带预览功能_flexsc.zip"暗示了我们关注的是一个使用Flex实现的图片上传组件,该组件支持用户在上传前预览图片。在Flex中实现这样的功能,我们需要考虑以下几个关键知识点: 1. **图片上传组件**:...

    Flex上传压缩文件到服务器路径并解压存进数据库

    在IT行业中,文件上传是常见的应用场景...综上所述,这个示例涵盖了客户端与服务器之间的通信、文件上传处理、文件压缩解压技术以及数据库操作等多个重要IT知识点。理解并实践这些技术对于提升Web开发能力非常有帮助。

    Flex在线word

    这里提到的"Java版图片上传服务端"是指服务器端使用Java语言实现的图片处理服务,它负责接收用户上传的图片,可能包括图片的压缩、格式转换、存储等操作,以确保图片能顺利集成到Word文档中。Java因其稳定性和跨平台...

    blog.zip_flex_flex blog

    1. **images_1.7z - images_4.7z**:这些可能是博客系统中的图片资源,如用户头像、装饰元素、图标等,分别打包为7z格式的压缩文件。 2. **part1.7z 和 part2.7z**:可能包含较大文件的分块,便于上传和下载,通常在...

    flex C# 在线拍照

    在本场景中,Flex可能被用来创建前端的拍照和上传组件,包括启动摄像头、捕获图像以及将图片数据发送到服务器的接口。 2. C#与ASP.NET:C#是.NET Framework的一部分,常用于构建Web服务和Web应用程序。在在线拍照的...

    Flex超炫相册

    在实际应用中,类似这样的图片会被上传到服务器并存储在数据库或文件系统中,然后通过Flex客户端展示给用户。 在Flex相册项目中,关键的技术点可能包括: - Flex组件库的使用:如Canvas、Image、Button等,用于...

    微信小程序 九宫格 图片上传

    需要注意的是,微信小程序对上传到服务器的图片大小有限制,通常需要确保图片压缩后不超过2M。 图片处理完成后,使用`wx.uploadFile`接口将图片上传到服务器。该接口需要传入服务器的URL、本地文件路径和一些额外的...

    Flex 的 Adobe AIR快速入门

    - **文件上传**: 通过集成文件选择器组件并使用FileReference类来实现文件上传功能。 - **JPEG文件处理**: 在上传过程中可能会涉及到JPEG文件的处理,如预览、压缩等。 3. **构建文本文件编辑器** - **文本编辑*...

    mFileUpload.rar_FlashMX/Flex源码_FlashMX_

    《深入理解FlashMX/Flex多文件上传与JPG图片压缩技术》 在互联网应用中,文件上传是一项常见的功能,尤其在多媒体分享、社交网络和在线协作平台中更是必不可少。本篇将详细介绍基于FlashMX/Flex的多文件上传及JPG...

    微信小程序原生自定义上传图片

    综上所述,微信小程序的原生自定义图片上传功能涵盖了权限管理、图片选择与预览、图片处理、上传、错误处理等多个环节,开发者可以根据实际需求进行组合和扩展,打造符合自己应用风格的图片上传组件。同时,通过样式...

    在线拍照 c# flex+fluorineFx+webservices

    在这个系统中,C#创建的Web服务可能提供了拍照、上传图片和处理图片等API接口,供Flex客户端调用。 **压缩包子文件的文件名称列表**: - `from.gif`:这可能是一个示例图像,用于展示或测试拍照系统的功能。 - `...

    uniapp图片上传

    综上所述,uniAPP图片上传涉及到前端UI设计、图片处理、网络请求、组件化开发等多个方面,结合提供的文件,我们可以构建一个完整的图片上传功能,并根据实际需求进行定制和优化。在实际开发中,还需要注意错误处理、...

    Flex-Avater:仿微博头像上传(Flex版)

    9. **图片压缩**:在上传前,Flex-Avater可能还包括对图像进行压缩的步骤,以减少上传的数据量和服务器存储空间。这通常通过JavaScript库如`html2canvas`和`FileReader` API来实现。 10. **错误处理**:良好的错误...

    FLEX在线照相

    在Flex应用中,library.swf可能包含了用户界面元素、图片和其他视觉资产。 2. **catalog.xml** - 这个文件可能是一个元数据文件,用于描述SWF文件中的资源,比如库中各个组件的信息。它可能用于编译时或运行时动态...

    微信小程序实现上传多张图片、删除图片

    微信小程序实现上传多张图片和删除图片的功能涉及到小程序的前端界面设计、事件处理以及后端的图片上传接口调用。以下是根据给定文件中的信息总结出的相关知识点。 ### 微信小程序上传图片 #### 前端实现 1. **...

Global site tag (gtag.js) - Google Analytics