[카테고리:] Flash

  • The XMLLoader class has been revised.

    기존에 try…catch 구문을 이용해서 만들었던 XMLLoader(XMLLoaderOld로 변경)는 몇 가지 문제점들을 포함하고 있었습니다. Wooyaggo님이 URLStream 객체를 사용하여 만든 XMLLoader 클래스를 보고서 저도 URLStream 객체를 사용하도록 수정해 보았습니다.

    XMLLoader 파일 다운로드

    그런데 이벤트 관련해서 이런식으로 사용하는 것이 옳은 것인지 모르겠네요. 많은 지적 부탁드립니다.

    /**
     * XMLLoader
     * XMLLoader class loads an external text file and decodes the data with the provided character set.
     * If you loads a text file encoded in the euc-kr encoding via an URLLoader, frequently, the source data is currupted.
     * To avoid this problem, uses URLStream instead of URLLoader.
     *
     * XMLLoader is the modified version of the XMLLoaderOld class.
     * This code is inspired by Wooyaggo's article(http://wooyaggo.tistory.com/116).
     * 
     *
     * @author: Han Sanghun (http://hangunsworld.com, hanguns@gmail.com)
     * @created: 2008 03 28
     * @last modified: 2008 06 06
     */
     
     /*
    Licensed under the MIT License
    
    Copyright (c) 2008 Han Sanghun
    
    Permission is hereby granted, free of charge, to any person obtaining a copy of
    this software and associated documentation files (the "Software"), to deal in
    the Software without restriction, including without limitation the rights to
    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
    the Software, and to permit persons to whom the Software is furnished to do so,
    subject to the following conditions:
    
    The above copyright notice and this permission notice shall be included in all
    copies or substantial portions of the Software.
    
    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
    FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
    COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
    IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
    CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    
    http://hangunsworld.com/classes/com/hangunsworld/net/
    */
    
    package com.hangunsworld.net{
    	
    	import	flash.events.*;
    	import	flash.net.URLLoader;
    	import	flash.net.URLRequest;
    	import	flash.net.URLStream;
    	
    	
    	public class XMLLoader{
    		
    		private var us:URLStream;
    		private var ul:URLLoader;
    		private var ur:URLRequest;
    		
    		private var encode:String;
    		
    		public var data:String = "";
    		
    		
    		/**
    		 * XMLLoader constructor
    		 */
    		public function XMLLoader(){
    			
    			us = new URLStream();
    			ul = new URLLoader();
    			
    		}// end constructor
    		
    		
    		/**
    		 * Adds event listeners to the URLLoader object and the URLStream object.
    		 */
    		public function addEventListener(type:String, listener:Function, useCapture:Boolean=false, priority:int=0, useWeakReference:Boolean=false):void{
    			ul.addEventListener(type, listener, useCapture, priority, useWeakReference);
    			us.addEventListener(type, agentListener, useCapture, priority, useWeakReference);
    		}// end addEventListener
    		
    		/**
    		 * Removes event listeners from the URLLoader object and the URLStream object.
    		 */
    		public function removeEventListener(type:String, listener:Function, useCapture:Boolean=false):void{
    			ul.removeEventListener(type, listener, useCapture);
    			us.removeEventListener(type, agentListener, useCapture);
    		}// end removeEventListener
    		
    		
    		/**
    		 * Loads external data via the URLStream object,
    		 * and sets the character set with the provied string.
    		 *
    		 * @param pUr The URLRequest object.
    		 * @param pEncode The string denoting the character set to use to interpret the bytes. [OPTIONAL]
    		 */
    		public function load(pUr:URLRequest, pEncode:String="utf-8"):void{
    			
    			encode = pEncode;
    			
    			ur = pUr;
    			us.load(ur);
    			
    		}// end load
    		
    		
    		/**
    		 * Dispatches events through the URLLoader object.
    		 */
    		private function agentListener(e):void{
    			
    			if(e.type == Event.COMPLETE){
    				// If the event's type is Event.COMPLETE, decodes the loaded data using the provided character set.
    				var str:String = us.readMultiByte(us.bytesAvailable, encode);
    				// Puts the decoded data into the URLLoader object.
    				data = str;
    				ul.data = str;
    			}
    			
    			ul.dispatchEvent(e.clone());
    			
    		}// end agentListener
    		
    		
    	}// end class
    }// end package

    Usage example.

    import	com.hangunsworld.net.XMLLoader;
    
    var xloader:XMLLoader = new XMLLoader();
    
    xloader.addEventListener(Event.COMPLETE, loaded);
    xloader.addEventListener(IOErrorEvent.IO_ERROR, errored);
    xloader.addEventListener(ProgressEvent.PROGRESS, progressed);
    
    xloader.load(new URLRequest(path), "euc-kr");
    
    
    function loaded(e:Event):void{
    	trace("COMPLETE");
    	var xml:XML = new XML(xloader.data);
    	trace(xml);
    }
    
    function errored(e:IOErrorEvent):void{
    	trace("IOERROR");
    }
    
    function progressed(e:ProgressEvent):void{
    	trace("PROGRESS - " + e.bytesTotal + " : " + e.bytesLoaded);
    }
  • XMLLoader, a custom class.

    I devised the XMLLoader class to avoid the URLLoader bug that I posted on FlaLab.com.
    Related links
    예전에 FlaLab에 올렸던 URLLoader의 버그를 회피하기 위해서 만든 XMLLoader 클래스 입니다.
    참고 링크
    私がFlaLab.comに書いたURLLoaderのバーグを回避するためにXMLLoaderクラスを作りました。
    参考リンク

    http://www.flalab.com/phpBB2/viewtopic.php?t=1791
    http://www.flalab.com/phpBB2/viewtopic.php?t=2228

    /**
     * XMLLoader
     *
     * XMLLoader class loads and validates an XML file.
     * If you loads a text file encoded in the euc-kr encoding via an URLLoader, frequently, the source data is currupted.
     * To avoid this problem, parses the loaded data into an XMLDocument,
     * then, parses the first node of the XMLDocument into an XML.
     * If an error has been occured, reloads the XML data.
     * 
     *
     * @author: Han Sanghun (http://hangunsworld.com, hanguns@gmail.com)
     * @created: 2008 02 28
     * @last modified: 2008 02 29
     */
    
    
    package com.hangunsworld.as3.net{
    	
    	import	flash.events.*;
    	import	flash.net.*;
    	import	flash.utils.Timer;
    	import	flash.xml.*;
    	
    	
    	public class XMLLoader{
    		
    		
    		private var path:String;
    		private var returnFunction:Function;
    		private var errorFunction:Function;
    		
    		private var timer:Timer;
    		private var xml:XML;
    		
    		private var xml_ul:URLLoader;
    		private var xml_ur:URLRequest;
    		private var xml_uv:URLVariables;
    		
    		/**
    		 * XMLLoader constructor
    		 *
    		 * @param pPath A path of an XML file
    		 * @param okFunc A function to call when the XML is loaded successfully
    		 * @param errorFunc A function to call when an IOError has occured
    		 */
    		public function XMLLoader(pPath:String, okFunc:Function=null, errorFunc:Function=null){
    			
    			path = pPath;
    			returnFunction = okFunc;
    			errorFunction = errorFunc
    			
    			XML.ignoreWhitespace = true;
    			XML.ignoreComments = true;
    			
    			
    			// Initializes NET objects
    			xml_ul = new URLLoader();
    			xml_ul.addEventListener (Event.COMPLETE, xmlCompleteListener);
    			xml_ul.addEventListener (IOErrorEvent.IO_ERROR, errorListener);
    			
    			xml_ur = new URLRequest();
    			xml_ur.url = path;
    			
    			xml_uv = new URLVariables();
    			
    			
    			// Initializes Timer object
    			timer = new Timer(50, 1);
    			timer.addEventListener(TimerEvent.TIMER, timerListener);
    			
    			timer.start();
    
    			
    		}// end constructor
    		
    		
    		/**
    		 * Timer EventListener
    		 * Loads an XML file after some time
    		 */
    		private function timerListener(evt:TimerEvent):void{
    			loadXML();
    		}// end timerListener
    		
    		
    		/**
    		 * Loads an XML file
    		 */
    		private function loadXML():void{
    			
    			if(path.indexOf("?") >= 0){
    				// If the url already contains parameters, attaches the random seed to the end of the url
    				xml_ur.url = path + "&randomSeed=" + Math.floor(Math.random() * 1000000);
    			}else{
    				// If the url does not contain parameters, uses an URLVariable object
    				xml_uv.randomSeed = Math.floor(Math.random() * 1000000);
    				xml_ur.data = xml_uv;
    			}
    			
    			xml_ul.load (xml_ur);
    			
    		}// end loadXML
    		
    		
    		/**
    		 * XML Complete EventListener
    		 */
    		private function xmlCompleteListener(evt:Event):void{
    			
    			// Sets the defualt parse state to false
    			var parsed:Boolean = false;
    			
    			var str:String = evt.target.data;
    			
    			var xmldoc:XMLDocument = new XMLDocument();
    			xmldoc.ignoreWhite = true;
    			
    			try{
    				
    				// Parses the loaded data into an XMLDocument
    				xmldoc.parseXML(str);
    				
    				// Gets a string from the first node of the XMLDocument
    				str = xmldoc.firstChild.toString();
    				
    				// Parses the string into an XML
    				xml = new XML(str);
    				
    				// If no error has occured, sets the parse stae to true
    				parsed = true;
    				
    			}catch(e){
    				
    				// If an error occured, loads the XML again
    				timer.start();
    				
    			}// end try catch
    			
    			
    			// If the parse process done without errors and the returnFunction is NOT null, returns the XML data
    			if(parsed){
    				if(returnFunction != null){
    					returnFunction(xml);
    				}
    			}
    			
    			
    		}// end xmlCompleteListener
    		
    		/**
    		 * XML IOError EventListener
    		 */
    		private function errorListener(evt:IOErrorEvent):void{
    			
    			if(errorFunction != null){
    				errorFunction(evt);
    			}
    			
    		}// end xmlErrorListener
    		
    		
    	}// end class
    	
    }// end package
    import	com.hangunsworld.as3.net.XMLLoader;
    
    var xloader:XMLLoader;
    xloader = new XMLLoader(xmlPath, xmlLoaded, xmlErrorListener);
    
    function xmlLoaded(xx:XML):void{
    	// xml loaded
    }
    
    function xmlErrorListener(evt:IOErrorEvent):void{
    	trace("xml load error");
    }
  • Array.length is a read-write property.

    Array.length is a read-write property. I should’ve know it.
    I just thought it was a read-only property. I came to know it reading a copy of EAS3.0.
    Array.length 속성이 리드-라이트 였네요. 이런걸 지금까지 모르고 있었다니…
    당연히 Read-only일 거라고 생각하고 있었는데, EAS3.0을 보다가 알게 되었네요.
    Array.lengthがread-write属性だったんですね。なぜ今まで知らなかったんだろう……
    当然read-onlyだと思っていったのに、EAS3.0を読みながら分かった。

    length property
    length:uint [read-write]

    Language Version : ActionScript 3.0
    Player Version : Flash Player 9

    A non-negative integer specifying the number of elements in the array. This property is automatically updated when new elements are added to the array. When you assign a value to an array element (for example, my_array[index] = value), if index is a number, and index+1 is greater than the length property, the length property is updated to index+1.

    Note: If you assign a value to the length property that is shorter than the existing length, the array will be truncated.

    quote from ActionScript 3.0 Language Reference

    var arr:Array = new Array(0, 1, 2, 3, 4, 5, 6);
    trace(arr);// output 0,1,2,3,4,5,6
    arr.length = 4;
    trace(arr);// output 0,1,2,3
    If the newly assigned length is shorter than the existing value, items whose index is larger than the length will be removed from the array and the array will be shortened to the specified length. In some cases, it is more useful than Array.slice() or Array.splice() methods.
    위와 같이 length에 현재 길이보다 작은 값을 입력하면, length 이후의 아이템들을 제거하고 배열이 입력받은 길이로 줄어들게 됩니다. 경우에 따라서는 Array.slice(), Array.splice() 보다 유용할 것 같네요.
    若し、新しいlengthが現在のlengthより少ないと、それ以後の配列要素は取り去れて、その配列の長さは短くなります。時折Array.slice()やArray.splice()メソッドより便利そうです。
  • Saving an image with AS3 and PHP: 3. ByteArray

    The following ActionScript 3 code is used to save GIF image that is encoded using GIFEncoder. I use GIFEncoder, distributed via ByteArray.org, to encode GIF files.
    다음은 GIFEncoder를 이용하여 인코딩한 GIF 파일을 저장하는 액션스크립트3 코드입니다. GIF 파일을 인코딩하기 위해서, ByteArray.org에서 배포하는 GIFEncoder를 사용하였습니다.
    これはGIFEncoderを使用してGIFファイルを保存するActionScript3のコードです。GIFファイルをエンコードするために、ByteArray.comで配布されているGIFEncoderを使いました。
    // Imports the GIFEndocer class by Thibault Imbert.
    // You can download it from ByteArray.org.
    import org.gif.encoder.GIFEncoder;
    
    var serverPath:String = "/";
    
    // Initializes GIFEncoder
    var myGIFEncoder:GIFEncoder = new GIFEncoder();
    myGIFEncoder.setRepeat(0);
    myGIFEncoder.setDelay (300);
    
    // Initializes an URLLoader object to upload a file stream.
    var ul:URLLoader = new URLLoader();
    ul.addEventListener(Event.COMPLETE, saveDone);
    
    var urh:URLRequestHeader = new URLRequestHeader("Accept","image/gif");
    var BOUNDARY:String = "---------------------------7d76d1b56035e";
    
    /**
     * Starts the gif encoding when clicks on the stage.
     */
    stage.addEventListener(MouseEvent.CLICK, generateGIF);
    function generateGIF(evt:MouseEvent):void{
    	
    	// Starts the gif encoder.
    	myGIFEncoder.start();
    	
    	// Add frame.
    	var bd:BitmapData = new BitmapData(100, 100, false, Math.round(0xFFFFFF*Math.random()));
    	myGIFEncoder.addFrame(bd);
    	
    	// Finishes the gif encoder.
    	myGIFEncoder.finish();
    	
    	// Starts the upload process.
    	uploadGIF();
    	
    }// end generateGIF
    
    /**
     * Generates a file stream and upload it.
     */
    function uploadGIF():void{
    	
    	// Retrieves the file stream from the GIF Encoder.
    	var myGIFStream:ByteArray = myGIFEncoder.stream;
    	var filename:String = "test.gif";
    	
    	// Creates the file header.
    	var formData:String  =  "--" + BOUNDARY + '\r\nContent-Disposition: form-data; name="Filedata"; filename="' + filename + '"\r\nContent-Type: application/octet-stream\r\n\r\n';
    	var formData2:String = "\r\n";
    	formData2 += "--" + BOUNDARY + '\r\nContent-Disposition: form-data; name="Filedata"\r\n\r\nSubmit Query\r\n';
    	formData2 += "--" + BOUNDARY + '--';
    	
    	
    	// Conbines the header and the file stream.
    	var dataArray:ByteArray = new ByteArray();
    	dataArray.writeMultiByte(formData,"ascii");
    	for(var k:uint=0; k
    
    Special thanks to Kim Eung. He devised the draft of the PHP and AS3 codes. Furthermore, he allowed me to open them to the public.
    이 PHP와 AS3 코드의 기틀을 만들고, 이 소스를 공개하는데 흔쾌히 동의하신, 김응 실장님에게 진심으로 감사드립니다.
  • Saving an image with AS3 and PHP: 2. FileReference

    The following code is an ActionScript 3.0 code that uploads files via FileReference.
    다음은 FileReference를 이용하여 파일을 업로드하는 액션스크립트3 코드입니다.
    Sorry, Japanese translation is not yet available.
    var serverPath:String = "/";
    
    // Creates a FileReference object.
    var fr:FileReference = new FileReference();
    var frFilter:FileFilter = new FileFilter("JPGs", "*.jpg");
    
    // Adds events to the FileReference object.
    fr.addEventListener(Event.SELECT, fileSelected);
    fr.addEventListener(DataEvent.UPLOAD_COMPLETE_DATA, fileUploaded);
    fr.addEventListener(ProgressEvent.PROGRESS, fileProgress);
    fr.addEventListener(IOErrorEvent.IO_ERROR, errorOccured);
    
    
    /**
     * Executes when a user selects a file to upload.
     */
    function fileSelected(evt:Event):void{
    	
    	// Checks the size of the file.
    	if(fr.size > 200*1024){
    		trace("You can NOT upload an image lagerer than 200KB.");
    	}else{
    		var ur:URLRequest = new URLRequest();
    		ur.url = serverPath + "test/uploadok.php";
    		
    		// Puts newName parameter, to avoid the multi-byte filename problem.
    		var uv:URLVariables = new URLVariables();
    		uv.newName = "upload.jpg";
    		
    		ur.data = uv;
    		
    		// Starts uploading.
    		fr.upload(ur);
    	}// end if else [fr.size]
    	
    }// end fileSelected
    
    
    /**
     * Executes when a file upload is finished.
     */
    function fileUploaded(evt:DataEvent):void{
    	trace(evt.data);
    }// end fileUploaded
    
    /**
     * Executes while uploading a file.
     */
    function fileProgress(evt:ProgressEvent):void{
    	//trace(evt.bytesLoaded + " / " + evt.bytesTotal);
    }// end fileProgress
    
    /**
     * Executes when an IO error occurs.
     */
    function errorOccured(evt:IOErrorEvent):void{
    	trace("IO error has occured.");
    }// end errorOccured
    
    
    /**
     * Shows the file browser when clicks on the stage.
     */
    stage.addEventListener(MouseEvent.MOUSE_DOWN, clicked);
    function clicked(evt:MouseEvent):void{
    	fr.browse([frFilter]);
    }
    In line 27 through 30, I assign newName parameter to an URLVariables object. This is to avoid IO error which occurs if the filename contains 2-byte characters. If you let the serverscript rename the uploaded file, this is not needed.
    27-30번째 줄을 보면, URLVariables 객체에 newName 파라메터를 설정했습니다. 이것은 파일명에 한글과 같은 2바이트 문자가 포함된 경우 서버에서 파일 저장시에 IO 에러가 발생하기 때문에, 이를 피하기 위해서 newName에 별도의 파일명을 저장한 것입니다. 만약 서버측에서 파일명을 변경하도록 구성되어 있다면, 이 부분은 필요 없습니다.
    var uv:URLVariables = new URLVariables();
    uv.newName = "upload.jpg";
    
    ur.data = uv;