由于项目需要,在客户上传搭配的过程中要实现图片在浏览器预览的功能,实在是纠结。思考过,个人认为要实现图片的本地预览可以通过编写ActiveX控件或者使用Flash做到。当然编写ActiveX控件会在浏览器端出现控件安装的过程,十分不友好,况且很多浏览器认为ActiveX控件是不安全的会屏蔽,只能抛弃。本以为Flash实现会很容易,可是到做的时候才发现,Flash 10在真正支持图片的本地预览(FileReference),当然产品的需求还有些变态的,需要实现AS与JS的互调。贴出代码,并对关键点加以说明。
View Code
package
{
import com.yahoo.astra.fl.charts.axes.IClusteringAxis;
import fl.events.InteractionInputType;
import flash.display.*;
import flash.geom.Rectangle;
import flash.net.*;
import flash.text.*;
import flash.filters.*;
import flash.events.*;
import flash.system.Security;
import flash.external.ExternalInterface;
import fl.controls.Button;
import fl.controls.ProgressBar;
import fl.controls.ProgressBarMode;
/**
* ...
* @author Olar Tan
*/
public class Main extends Sprite
{
//fontColor=#ff4570;
//bgColor=#1a1a1a;
private const DEFAULT_UPLOAD_PAGE:String = "http://www.xxx.com/upload.aspx";
private const BOX_WIDTH:uint = 400;
private const BOX_HEIGHT:uint = 600;
private const STATE_CACHE:String = "cache";
private const STATE_UPLOAD:String = "upload";
[Embed(source = '../lib/bg.png')]
private var Pic:Class; //;
private var _filters:Array;
private var _file:FileReference;
private var _loader:Loader;
private var _progress:ProgressBar;
private var _state:String;
private var _buttons:Array;
private var _labels:Array;
private var _txts:Array;
private var _rect:Rectangle;
private var _state_txt:TextField;
private var _lblChoose:TextField;
private var _upload_url:String;
private var _contactId:String;
private var _isPkFlag:String;
private var _pkId:String;
private var _upload_complete_callback:String;
private var _pic:* = new Pic();
public function Main():void
{
if (stage) init();
else addEventListener(Event.ADDED_TO_STAGE, init);
}
private function init(e:Event = null):void
{
_upload_url = stage.loaderInfo.parameters["uploadURL"];
_contactId = stage.loaderInfo.parameters["contactId"];
_pkId = stage.loaderInfo.parameters["pkId"];
_isPkFlag = stage.loaderInfo.parameters["isPkFlag"];
_upload_complete_callback = stage.loaderInfo.parameters["uploadCompleteCallback"];
ExternalInterface.addCallback(stage.loaderInfo.parameters["outerUploadPhotoCallback"], outerEventUploadPhoto);
ExternalInterface.addCallback(stage.loaderInfo.parameters["outerChoosePhotoCallback"],outerEventChoosePhoto);
removeEventListener(Event.ADDED_TO_STAGE, init);
Security.allowDomain("*");
_buttons = [];
_txts = [];
_labels = ["文件名称:","文件类型:","文件大小:","修改时间:"];
_rect = new Rectangle(0, 30, 400, 600);
_state = STATE_CACHE;
this.addChild(_pic);
//背景;
this.graphics.beginFill(0xffffff);
this.graphics.drawRect(0, 0, 400, 30);
this.graphics.endFill();
//标题;
var label:TextField;
label = getLabel("搭配照片:", getTextFormat(0x333333, 14, false));
label.x = 0;
label.y = 5;
this.addChild(label);
//重新选择按钮
_lblChoose = getLabel("重新选择照片", getTextFormat(0xff4570, 14, true, true), true);
_lblChoose.x = 90;
_lblChoose.y = 5;
_lblChoose.addEventListener(MouseEvent.CLICK, clickHandler);
this.addChild(_lblChoose);
_lblChoose.visible = false;
for (var i:uint = 0; i < _labels.length; i++ ) {
label = getLabel(_labels[i], getTextFormat(0x333333, 12), false, false);
label.x = _rect.right+5;
label.y = _rect.y + 25 * i;
label.width = 280;
label.height = 20;
_txts.push(label);
//this.addChild(label);
}
//状态
_state_txt = getLabel("状态:", getTextFormat(0x333333, 12));
_state_txt.x = 170;
_state_txt.y = 5;
//this.addChild(_state_txt);
//按钮选择
var button:Button;
button = getButton("选择文件", 130);
button.move(135, 220);
//按钮上传
button = getButton("上传文件", 80);
button.move(300, 5);
button.enabled = false;
button.visible = false;
//进度条;
_progress = new ProgressBar();
_progress.move(20, 80);
_progress.setSize(290,22);
_progress.mode = ProgressBarMode.MANUAL;
//this.addChild(_progress);
//文件类型;
_filters = [];
var filter:FileFilter;
filter = new FileFilter("所有支持图片文件(*.jpg,*.jpeg,*.gif,*.png)", "*.jpg;*.jpeg;*.gif;*.png");
_filters[_filters.length] = filter;
filter = new FileFilter("JPEG files(*.jpg,*.jpeg)","*.jpg;*.jpeg");
_filters[_filters.length] = filter;
filter = new FileFilter("GIF files (*.gif)","*.gif");
_filters[_filters.length] = filter;
filter = new FileFilter("PNG files(*.png)","*.png");
_filters[_filters.length] = filter;
_file = new FileReference();
_file.addEventListener(Event.COMPLETE, fileHandler);
_file.addEventListener(DataEvent.UPLOAD_COMPLETE_DATA, fileHandler);
_file.addEventListener(Event.SELECT, fileHandler);
_file.addEventListener(Event.OPEN, fileHandler);
_file.addEventListener(ProgressEvent.PROGRESS, fileHandler);
_file.addEventListener(SecurityErrorEvent.SECURITY_ERROR, fileHandler);
_file.addEventListener(IOErrorEvent.IO_ERROR, fileHandler);
_file.addEventListener(HTTPStatusEvent.HTTP_STATUS, fileHandler);
_loader = new Loader();
_loader.contentLoaderInfo.addEventListener(Event.COMPLETE, loadHandler);
this.addChild(_loader);
}
public function get state():String {
return _state;
}
private function clickHandler(event:MouseEvent):void {
switch(event.target) {
case _lblChoose:
case _buttons[0]:
_file.browse(_filters);
break;
case _buttons[1]:
var urlRequest:URLRequest = new URLRequest(_upload_url);
_file.upload(urlRequest);
_state = STATE_UPLOAD;
_buttons[0].enabled = false;
_buttons[1].enabled = false;
break;
}
}
private function outerEventUploadPhoto(mediaStyle:int,mediaDesc:String):void {
try
{
var urlRequest:URLRequest = new URLRequest(_upload_url+"?contactId="+_contactId+"&pkId="+_pkId+"&isPkFlag="+_isPkFlag+"&mediaStyle="+mediaStyle+"&mediaDesc="+mediaDesc);
_file.upload(urlRequest);
_state = STATE_UPLOAD;
}
catch(e:Error){}
}
private function outerEventChoosePhoto():void {
debug("选择图片.");
}
private function loadHandler(event:Event):void {
_buttons[0].visible = false;
_lblChoose.visible = true;
_loader.scaleX = _loader.scaleY = 1;
var w:uint = _loader.width;
var h:uint = _loader.height;
if (w > _rect.width || h > _rect.height) {
var ip:Number = w / h;
var lp:Number = _rect.width / _rect.height;
_loader.width = (ip > lp)?_rect._rect.height*ip;
_loader.height = (ip > lp)?_rect.width / ip:_rect.height;
}
_loader.x = _rect.x + (_rect.width - _loader.width) / 2;
_loader.y = _rect.y + (_rect.height - _loader.height) / 2;
_loader.visible = true;
}
private function fileHandler(event:Event):void {
var result:String = '';
switch(event.type) {
case Event.COMPLETE:
if(state == STATE_CACHE){
_loader.loadBytes(_file.data);
}
break;
case DataEvent.UPLOAD_COMPLETE_DATA:
debug("图片上传完成!");
_buttons[0].enabled = true;
_buttons[1].enabled = false;
_progress.setProgress(0, 1);
var dEvent:DataEvent = event as DataEvent;
result= dEvent.data.toString();
break;
case Event.SELECT:
_txts[0].text = _labels[0] + _file.name;
_txts[1].text = _labels[1] + _file.type;
_txts[2].text = _labels[2] + ((_file.size > 1024 * 1024)?Math.round(_file.size * 10 / (1024*1024))/10
+ "MB":Math.round(_file.size * 10 / 1024)/10 + "KB");
_txts[3].text = _labels[3] + date2str(_file.modificationDate);
_buttons[0].enabled = true;
_buttons[1].enabled = true;
_file.load();
_state = STATE_CACHE;
this.removeChild(_pic);
_loader.visible = false;
debug("图片已经准备!");
break;
case Event.OPEN:
if(state == STATE_UPLOAD){
debug("正在上传图片...");
}
break;
case ProgressEvent.PROGRESS:
if (state == STATE_UPLOAD) {
var pEvent:ProgressEvent = event as ProgressEvent;
_progress.setProgress(pEvent.bytesLoaded, pEvent.bytesTotal);
}
break;
case SecurityErrorEvent.SECURITY_ERROR:
case IOErrorEvent.IO_ERROR:
case HTTPStatusEvent.HTTP_STATUS:
if (state == STATE_UPLOAD) {
debug("图片上传失败!");
_buttons[0].enabled = true;
_buttons[1].enabled = true;
}else {
debug("图片缓冲失败!");
}
_progress.setProgress(0, 1);
result = "[00]-[上传失败]";
break;
}
if (result!='' && ExternalInterface.available)
{
ExternalInterface.call(_upload_complete_callback, result);
}
}
private function getButton(lbl:String,uint=120):Button {
var button:Button = new Button();
button.label = lbl;
button.setSize(width, 34);
button.setStyle("textFormat", getTextFormat());
button.setStyle("disabledTextFormat", getTextFormat(0x999999));
button.setStyle("textPadding",4);
button.addEventListener(MouseEvent.CLICK, clickHandler);
this.addChild(button);
_buttons.push(button);
return button;
}
private function getLabel(label:String, format:TextFormat, isHand:Boolean=false,selectable:
Boolean = false, autoSize:Boolean = true):TextField {
var lbl:TextField = new TextField();
lbl.selectable = selectable;
lbl.defaultTextFormat = format;
if(autoSize){
lbl.autoSize = TextFieldAutoSize.LEFT;
}
if (isHand) lbl.htmlText = "<a href=\"#\">" + label + "</a>";
else lbl.text = label;
return lbl;
}
private function getTextFormat(color:uint=0x000000,size:uint = 16,bold:Boolean=false,underline:Boolean=false):
TextFormat {
var format:TextFormat = new TextFormat();
format.font = "宋体";
format.color = color;
if(underline)format.underline = true;
format.size = size;
format.bold = bold;
return format;
}
private function getTextFormatWithUnderline(color:uint=0x000000,size:uint = 16,bold:Boolean=false):
TextFormat {
var format:TextFormat = new TextFormat();
format.font = "宋体";
format.color = color;
format.underline = true;
format.size = size;
format.bold = bold;
return format;
}
private function getLabelFilter(color:uint=0xFFFFFF):BitmapFilter {
var alpha:Number = 0.8;
var blurX:Number = 2;
var blurY:Number = 2;
var strength:Number = 3;
var inner:Boolean = false;
var knockout:Boolean = false;
var quality:Number = BitmapFilterQuality.HIGH;
return new GlowFilter(color,
alpha,
blurX,
blurY,
strength,
quality,
inner,
knockout);
}
private function date2str(day:Date):String {
var str:String = day.getFullYear() + "-";
str += num2str(day.getMonth() + 1) + "-";
str += num2str(day.getDate()) + " ";
str += num2str(day.getHours()) + ":";
str += num2str(day.getMinutes()) + ":";
str += num2str(day.getSeconds());
return str;
}
private function num2str(val:Number):String {
var str:String = "00" + val;
return str.substr(str.length - 2, 2);
}
private function debug(message:String):void {
_state_txt.text = message;
}
}
}
{
import com.yahoo.astra.fl.charts.axes.IClusteringAxis;
import fl.events.InteractionInputType;
import flash.display.*;
import flash.geom.Rectangle;
import flash.net.*;
import flash.text.*;
import flash.filters.*;
import flash.events.*;
import flash.system.Security;
import flash.external.ExternalInterface;
import fl.controls.Button;
import fl.controls.ProgressBar;
import fl.controls.ProgressBarMode;
/**
* ...
* @author Olar Tan
*/
public class Main extends Sprite
{
//fontColor=#ff4570;
//bgColor=#1a1a1a;
private const DEFAULT_UPLOAD_PAGE:String = "http://www.xxx.com/upload.aspx";
private const BOX_WIDTH:uint = 400;
private const BOX_HEIGHT:uint = 600;
private const STATE_CACHE:String = "cache";
private const STATE_UPLOAD:String = "upload";
[Embed(source = '../lib/bg.png')]
private var Pic:Class; //;
private var _filters:Array;
private var _file:FileReference;
private var _loader:Loader;
private var _progress:ProgressBar;
private var _state:String;
private var _buttons:Array;
private var _labels:Array;
private var _txts:Array;
private var _rect:Rectangle;
private var _state_txt:TextField;
private var _lblChoose:TextField;
private var _upload_url:String;
private var _contactId:String;
private var _isPkFlag:String;
private var _pkId:String;
private var _upload_complete_callback:String;
private var _pic:* = new Pic();
public function Main():void
{
if (stage) init();
else addEventListener(Event.ADDED_TO_STAGE, init);
}
private function init(e:Event = null):void
{
_upload_url = stage.loaderInfo.parameters["uploadURL"];
_contactId = stage.loaderInfo.parameters["contactId"];
_pkId = stage.loaderInfo.parameters["pkId"];
_isPkFlag = stage.loaderInfo.parameters["isPkFlag"];
_upload_complete_callback = stage.loaderInfo.parameters["uploadCompleteCallback"];
ExternalInterface.addCallback(stage.loaderInfo.parameters["outerUploadPhotoCallback"], outerEventUploadPhoto);
ExternalInterface.addCallback(stage.loaderInfo.parameters["outerChoosePhotoCallback"],outerEventChoosePhoto);
removeEventListener(Event.ADDED_TO_STAGE, init);
Security.allowDomain("*");
_buttons = [];
_txts = [];
_labels = ["文件名称:","文件类型:","文件大小:","修改时间:"];
_rect = new Rectangle(0, 30, 400, 600);
_state = STATE_CACHE;
this.addChild(_pic);
//背景;
this.graphics.beginFill(0xffffff);
this.graphics.drawRect(0, 0, 400, 30);
this.graphics.endFill();
//标题;
var label:TextField;
label = getLabel("搭配照片:", getTextFormat(0x333333, 14, false));
label.x = 0;
label.y = 5;
this.addChild(label);
//重新选择按钮
_lblChoose = getLabel("重新选择照片", getTextFormat(0xff4570, 14, true, true), true);
_lblChoose.x = 90;
_lblChoose.y = 5;
_lblChoose.addEventListener(MouseEvent.CLICK, clickHandler);
this.addChild(_lblChoose);
_lblChoose.visible = false;
for (var i:uint = 0; i < _labels.length; i++ ) {
label = getLabel(_labels[i], getTextFormat(0x333333, 12), false, false);
label.x = _rect.right+5;
label.y = _rect.y + 25 * i;
label.width = 280;
label.height = 20;
_txts.push(label);
//this.addChild(label);
}
//状态
_state_txt = getLabel("状态:", getTextFormat(0x333333, 12));
_state_txt.x = 170;
_state_txt.y = 5;
//this.addChild(_state_txt);
//按钮选择
var button:Button;
button = getButton("选择文件", 130);
button.move(135, 220);
//按钮上传
button = getButton("上传文件", 80);
button.move(300, 5);
button.enabled = false;
button.visible = false;
//进度条;
_progress = new ProgressBar();
_progress.move(20, 80);
_progress.setSize(290,22);
_progress.mode = ProgressBarMode.MANUAL;
//this.addChild(_progress);
//文件类型;
_filters = [];
var filter:FileFilter;
filter = new FileFilter("所有支持图片文件(*.jpg,*.jpeg,*.gif,*.png)", "*.jpg;*.jpeg;*.gif;*.png");
_filters[_filters.length] = filter;
filter = new FileFilter("JPEG files(*.jpg,*.jpeg)","*.jpg;*.jpeg");
_filters[_filters.length] = filter;
filter = new FileFilter("GIF files (*.gif)","*.gif");
_filters[_filters.length] = filter;
filter = new FileFilter("PNG files(*.png)","*.png");
_filters[_filters.length] = filter;
_file = new FileReference();
_file.addEventListener(Event.COMPLETE, fileHandler);
_file.addEventListener(DataEvent.UPLOAD_COMPLETE_DATA, fileHandler);
_file.addEventListener(Event.SELECT, fileHandler);
_file.addEventListener(Event.OPEN, fileHandler);
_file.addEventListener(ProgressEvent.PROGRESS, fileHandler);
_file.addEventListener(SecurityErrorEvent.SECURITY_ERROR, fileHandler);
_file.addEventListener(IOErrorEvent.IO_ERROR, fileHandler);
_file.addEventListener(HTTPStatusEvent.HTTP_STATUS, fileHandler);
_loader = new Loader();
_loader.contentLoaderInfo.addEventListener(Event.COMPLETE, loadHandler);
this.addChild(_loader);
}
public function get state():String {
return _state;
}
private function clickHandler(event:MouseEvent):void {
switch(event.target) {
case _lblChoose:
case _buttons[0]:
_file.browse(_filters);
break;
case _buttons[1]:
var urlRequest:URLRequest = new URLRequest(_upload_url);
_file.upload(urlRequest);
_state = STATE_UPLOAD;
_buttons[0].enabled = false;
_buttons[1].enabled = false;
break;
}
}
private function outerEventUploadPhoto(mediaStyle:int,mediaDesc:String):void {
try
{
var urlRequest:URLRequest = new URLRequest(_upload_url+"?contactId="+_contactId+"&pkId="+_pkId+"&isPkFlag="+_isPkFlag+"&mediaStyle="+mediaStyle+"&mediaDesc="+mediaDesc);
_file.upload(urlRequest);
_state = STATE_UPLOAD;
}
catch(e:Error){}
}
private function outerEventChoosePhoto():void {
debug("选择图片.");
}
private function loadHandler(event:Event):void {
_buttons[0].visible = false;
_lblChoose.visible = true;
_loader.scaleX = _loader.scaleY = 1;
var w:uint = _loader.width;
var h:uint = _loader.height;
if (w > _rect.width || h > _rect.height) {
var ip:Number = w / h;
var lp:Number = _rect.width / _rect.height;
_loader.width = (ip > lp)?_rect._rect.height*ip;
_loader.height = (ip > lp)?_rect.width / ip:_rect.height;
}
_loader.x = _rect.x + (_rect.width - _loader.width) / 2;
_loader.y = _rect.y + (_rect.height - _loader.height) / 2;
_loader.visible = true;
}
private function fileHandler(event:Event):void {
var result:String = '';
switch(event.type) {
case Event.COMPLETE:
if(state == STATE_CACHE){
_loader.loadBytes(_file.data);
}
break;
case DataEvent.UPLOAD_COMPLETE_DATA:
debug("图片上传完成!");
_buttons[0].enabled = true;
_buttons[1].enabled = false;
_progress.setProgress(0, 1);
var dEvent:DataEvent = event as DataEvent;
result= dEvent.data.toString();
break;
case Event.SELECT:
_txts[0].text = _labels[0] + _file.name;
_txts[1].text = _labels[1] + _file.type;
_txts[2].text = _labels[2] + ((_file.size > 1024 * 1024)?Math.round(_file.size * 10 / (1024*1024))/10
+ "MB":Math.round(_file.size * 10 / 1024)/10 + "KB");
_txts[3].text = _labels[3] + date2str(_file.modificationDate);
_buttons[0].enabled = true;
_buttons[1].enabled = true;
_file.load();
_state = STATE_CACHE;
this.removeChild(_pic);
_loader.visible = false;
debug("图片已经准备!");
break;
case Event.OPEN:
if(state == STATE_UPLOAD){
debug("正在上传图片...");
}
break;
case ProgressEvent.PROGRESS:
if (state == STATE_UPLOAD) {
var pEvent:ProgressEvent = event as ProgressEvent;
_progress.setProgress(pEvent.bytesLoaded, pEvent.bytesTotal);
}
break;
case SecurityErrorEvent.SECURITY_ERROR:
case IOErrorEvent.IO_ERROR:
case HTTPStatusEvent.HTTP_STATUS:
if (state == STATE_UPLOAD) {
debug("图片上传失败!");
_buttons[0].enabled = true;
_buttons[1].enabled = true;
}else {
debug("图片缓冲失败!");
}
_progress.setProgress(0, 1);
result = "[00]-[上传失败]";
break;
}
if (result!='' && ExternalInterface.available)
{
ExternalInterface.call(_upload_complete_callback, result);
}
}
private function getButton(lbl:String,uint=120):Button {
var button:Button = new Button();
button.label = lbl;
button.setSize(width, 34);
button.setStyle("textFormat", getTextFormat());
button.setStyle("disabledTextFormat", getTextFormat(0x999999));
button.setStyle("textPadding",4);
button.addEventListener(MouseEvent.CLICK, clickHandler);
this.addChild(button);
_buttons.push(button);
return button;
}
private function getLabel(label:String, format:TextFormat, isHand:Boolean=false,selectable:
Boolean = false, autoSize:Boolean = true):TextField {
var lbl:TextField = new TextField();
lbl.selectable = selectable;
lbl.defaultTextFormat = format;
if(autoSize){
lbl.autoSize = TextFieldAutoSize.LEFT;
}
if (isHand) lbl.htmlText = "<a href=\"#\">" + label + "</a>";
else lbl.text = label;
return lbl;
}
private function getTextFormat(color:uint=0x000000,size:uint = 16,bold:Boolean=false,underline:Boolean=false):
TextFormat {
var format:TextFormat = new TextFormat();
format.font = "宋体";
format.color = color;
if(underline)format.underline = true;
format.size = size;
format.bold = bold;
return format;
}
private function getTextFormatWithUnderline(color:uint=0x000000,size:uint = 16,bold:Boolean=false):
TextFormat {
var format:TextFormat = new TextFormat();
format.font = "宋体";
format.color = color;
format.underline = true;
format.size = size;
format.bold = bold;
return format;
}
private function getLabelFilter(color:uint=0xFFFFFF):BitmapFilter {
var alpha:Number = 0.8;
var blurX:Number = 2;
var blurY:Number = 2;
var strength:Number = 3;
var inner:Boolean = false;
var knockout:Boolean = false;
var quality:Number = BitmapFilterQuality.HIGH;
return new GlowFilter(color,
alpha,
blurX,
blurY,
strength,
quality,
inner,
knockout);
}
private function date2str(day:Date):String {
var str:String = day.getFullYear() + "-";
str += num2str(day.getMonth() + 1) + "-";
str += num2str(day.getDate()) + " ";
str += num2str(day.getHours()) + ":";
str += num2str(day.getMinutes()) + ":";
str += num2str(day.getSeconds());
return str;
}
private function num2str(val:Number):String {
var str:String = "00" + val;
return str.substr(str.length - 2, 2);
}
private function debug(message:String):void {
_state_txt.text = message;
}
}
}
可很明显看到,源码是AS3编写的,IDE选择使用FlashDevelop,开源软件。
环境:Flash CS4、net framework 2.、Flex SDK4.0、Java SDK 1.6、FlashDevelop
关键点:
1.获取外部参数通过stage.loaderInfo.parameter["Name"]
2.外部JS执行AS内部方法通过ExternalInterface.addCallback("outerEvent", outerEventCallback)
3.AS内部回调外部JS函数通过ExternalInterface.call("outerFunc", "arguments");