I am very new to Flex. I want to retrieve file's binary content using flex but failed. Here is the code so far:
// ActionScript file
package source.fileApi{
import flash.display.Sprite;
import flash.external.ExternalInterface;
import flash.system.Security;
import flash.utils.setTimeout;
import flash.net.FileReference;
import flash.net.FileFilter;
import flash.events.IOErrorEvent;
import flash.events.Event;
import flash.utils.ByteArray;
import mx.utils.URLUtil;
public class FileAPIMain {
private var debug:Boolean = false;
private var dataReaded:String;
private var fr:FileReference;
public function FileAPIMain():void{
ExternalInterface.addCallback("setDebug", setDebug);
ExternalInterface.addCallback("onLoadFileClick", onLoadFileClick);
ExternalInterface.call("FileReader.__onFlashInitialized");
}
public function log(message:String):void {
if (debug) {
ExternalInterface.call("FileReader.__log", encodeURIComponent("[FileReader] " + message));
}
}
public function setDebug(val:Boolean):void {
debug = val;
if (val) {
log("debug enabled");
}
}
public function onLoadFileClick():void{
//create the FileReference instance
fr = new FileReference();
//listen for when they select a file
fr.addEventListener(Event.SELECT, onFileSelect);
//listen for when then cancel out of the browse dialog
fr.addEventListener(Event.CANCEL,onCancel);
//open a native browse dialog that filters for text files
fr.browse();
}
private function onFileSelect(e:Event):void{
fr.removeEventListener(Event.SELECT, onFileSelect);
//listen for when the file has loaded
fr.addEventListener(Event.COMPLETE, onLoadComplete);
//listen for any errors reading the file
fr.addEventListener(IOErrorEvent.IO_ERROR, onLoadError);
//load the content of the file
fr.load();
}
private function onCancel(e:Event):void{
log("File Browse Canceled");
fr = null;
}
private function onLoadComplete(e:Event):void{
fr.removeEventListener(Event.COMPLETE, onLoadComplete);
//get the data from the file as a ByteArray
var data:ByteArray = fr.data as ByteArray;
dataReaded = data.readUTFBytes(data.bytesAvailable);
ExternalInterface.call("FileReader.__getSize", fr.size);
ExternalInterface.call("FileReader.__getName", fr.name);
ExternalInterface.call("FileReader.__getData", dataReaded);
ExternalInterface.call("FileReader.__takeAction");
//clean up the FileReference instance
fr = null;
}
private function onLoadError(e:IOErrorEvent):void{
log("Error loading file : " + e.text);
}
}
}
But this did not give me the binary content of the file.. Could any one please tell me how to retrieve the full binary content of the given file using Flex (I am using FP 10.0).....
If you user FLashPlayer 10+ then make use of FileReference.
See the pure AS3 sample below
var buttonShape:Shape = new Shape();
buttonShape.graphics.beginFill(0x336699);
buttonShape.graphics.drawCircle(50, 50, 25);
var button = new SimpleButton(buttonShape, buttonShape, buttonShape, buttonShape);
addChild(button);
var fileRef:FileReference= new FileReference();
button.addEventListener(MouseEvent.CLICK, onButtonClick);
function onButtonClick(e:MouseEvent):void
{
fileRef.browse([new FileFilter("Images", "*.jpg;*.gif;*.png")]);
fileRef.addEventListener(Event.SELECT, onFileSelected);
}
function onFileSelected(e:Event):void
{
fileRef.addEventListener(Event.COMPLETE, onFileLoaded);
fileRef.load();
}
function onFileLoaded(e:Event):void
{
// here we get the data
var theData:Object = e.target.data;
// next you can manipulate the data as you like! ;) depending on the type
}
Related
How can I take screen shot of Entire on Screen regular intervals (random between 2 to 5 minutes) without click event using Adobe flex and action script. Currently I am doing it with the Mouse_Up Event and then calling the timer and then saving each image with different name
package
{
import flash.desktop.NativeProcess;
import flash.desktop.NativeProcessStartupInfo;
import flash.display.Sprite;
import flash.display.StageAlign;
import flash.display.StageDisplayState;
import flash.display.StageScaleMode;
import flash.events.MouseEvent;
import flash.events.NativeProcessExitEvent;
import flash.events.TimerEvent;
import flash.filesystem.File;
import flash.system.Capabilities;
import flash.utils.Timer;
public class Grabber extends Sprite
{
private var stageCover:Sprite;
private var captureRect:Sprite;
private var sx:Number;
private var sy:Number;
private var np:NativeProcess;
private var npi:NativeProcessStartupInfo;
public function Grabber()
{
super();
stage.displayState = StageDisplayState.FULL_SCREEN_INTERACTIVE;
stage.align = StageAlign.TOP_LEFT;
stage.scaleMode = StageScaleMode.NO_SCALE;
stageCover = new Sprite();
stageCover.graphics.beginFill(0xFFFFFF, 0.01);
stageCover.graphics.drawRect(0, 0, Capabilities.screenResolutionX, Capabilities.screenResolutionY);
addChild(stageCover);
stage.addEventListener(MouseEvent.MOUSE_UP, onMouseUp);
captureRect = new Sprite();
captureRect.graphics.lineStyle(2, 0xFFFFFF);
addChild(captureRect);
np = new NativeProcess();
npi = new NativeProcessStartupInfo();
}
private function onTimerComplete( event:TimerEvent):void
{
captureRect.graphics.clear();
var args:Vector.<String> = new Vector.<String>();
args.push("-l");
sx =0;
args.push(sx.toString());
args.push("-t");
sy = 0 ;
args.push(sy.toString());
args.push("-r");
var a:Number = Capabilities.screenResolutionX;
args.push(a.toString());
args.push("-b");
var b:Number= Capabilities.screenResolutionY;
args.push(b.toString());
args.push("-out");
args.push(File.desktopDirectory.nativePath + "/grab.jpeg");
npi.arguments = args;
npi.executable = File.applicationDirectory.resolvePath("GrabberCommand.exe");
np.start(npi);
}
private function onMouseUp(event:MouseEvent):void
{
var timer:Timer=new Timer( 10*1000*Math.random(),1 );
timer.addEventListener( TimerEvent.TIMER, onTimerComplete );
timer.start();
}
}
}
XML Properties are
SystemChrome none
Transparent true
SupportedProfiles extendedDesktop
I actually did something like this before.
You will need a Timer that calls the following function at intervals (whatever intervals you like):
private function captureScreenshots(event:MouseEvent):void
{
var imgEnc:IImageEncoder;
var screenshotArray:Array = new Array();
if(myView.encodingCombo.selectedItem == "PNG")
{
imgEnc = pngEnc; //private const pngEnc:PNGEncoder = new PNGEncoder();
}
else
{
imgEnc = jpgEnc; //private const jpgEnc:JPEGEncoder = new JPEGEncoder();
}
var windowsArray:Array = NativeApplication.nativeApplication.openedWindows;
for each(var window:NativeWindow in windowsArray)
{
if(window && window.stage is IBitmapDrawable)
{
var imageSnapshot:ImageSnapshot = ImageSnapshot.captureImage(window.stage as IBitmapDrawable, 0, imgEnc);
screenshotArray.push(imageSnapshot);
}
}
windowsArray = null;
}
You can then use a FileStream to write them to a directory, but that would be a different question.
I m using flex4.6 and i wanted to run a .bat file from ma air application, is there any help ?
You can use NativeProcess class.
http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/desktop/NativeProcess.html
Try this
This class might helpful for you my_command.bat echo "Hello Native Process"
Before run applications (Projectname-app.xml) check supportedProfiles tag
desktop extendedDesktop mobileDevice exendedMobileDevice
to
extendedDesktop
package
{
import flash.desktop.NativeProcess;
import flash.desktop.NativeProcessStartupInfo;
import flash.events.ProgressEvent;
import flash.filesystem.File;
import mx.controls.Alert;
public class PlatformPackaging
{
private var nativeProcess:NativeProcess;
private var isErrorOccured:Boolean;
private var batFile:File;
private var cmdFile:File;
private function get isWindows():Boolean
{
return true;
}
public function PlatformPackaging()
{
}
public function start(targetPlatform:String):void
{
if(isWindows)
{
batFile = File.applicationDirectory.resolvePath("publish/my_command.bat");
cmdFile = new File("c:\\Windows\\System32\\cmd.exe");
}
proceedToPackaging();
}
private function proceedToPackaging():void {
var processArgs:Vector.<String> = new Vector.<String>;
processArgs.push("/c");
processArgs.push(batFile.nativePath);
var workingDirectory:File = File.applicationDirectory.resolvePath("publish/");
var nativeProcessStartupInfo:NativeProcessStartupInfo = new NativeProcessStartupInfo();
nativeProcessStartupInfo.arguments = processArgs;
nativeProcessStartupInfo.executable = cmdFile;
nativeProcessStartupInfo.workingDirectory = workingDirectory;
nativeProcess = new NativeProcess();
nativeProcess.addEventListener(ProgressEvent.STANDARD_ERROR_DATA,onStandardErrorOutputDataHandler);
nativeProcess.addEventListener(ProgressEvent.STANDARD_OUTPUT_DATA,onStandardOutputDataHandler);
nativeProcess.start(nativeProcessStartupInfo);
}
private function onStandardErrorOutputDataHandler(event:ProgressEvent) : void
{
var certResponse:String = nativeProcess.standardError.readUTFBytes(nativeProcess.standardError.bytesAvailable);
trace(certResponse);
nativeProcess.removeEventListener(ProgressEvent.STANDARD_ERROR_DATA,onStandardOutputDataHandler);
nativeProcess.exit();
}
Alert.show(certResponse,'Error');
}
protected function onStandardOutputDataHandler(event:ProgressEvent):void
{
var status:String = nativeProcess.standardOutput.readUTFBytes(nativeProcess.standardOutput.bytesAvailable);
Alert.show(status)
}
}
}
Please let me know any clarification.
I'm making a Flex mobile application with Flash Builder 4.6 And I have a question for a function I want to implement.
I have a declaration:
<s:HTTPService id="getXMLFile" fault="trace('No CCR found!')" result="getPatient(event)"
resultFormat="object" url="assets/CCR1.xml"/>
But this only points to one file and this has to be typed in.
Already now how to change the url and do the request again.
getXMLFile.url = "assets/CCR2.xml";
getXMLFile.send();
But I want to have some sort of function to check all the files in the "assets" package and to this code part for each file. So I want something like this:
for(var file:string in assets) {
getXMLFile.url = "assets/" + file;
getXMLFile.send();
}
Thx
<fx:Script>
<![CDATA[
import mx.rpc.events.FaultEvent;
import mx.rpc.events.ResultEvent;
//Create one xml having all URL, which you can parse on Flex side. Collect all URL in Array (ex:- fileArray),
//than you can loop it. You can call parseXML on creationComplete of your application.
private var fileArray:Array = new Array();
private var count:int = 0;
//Collect all URL in this fileArray.
private function parseXML():void
{
//parse XML and puch URL in fileArray
// xmlLength var is xml length.
var xmlLength:int;
for(var i:int;i<xmlLength ;i++)
{
var URL:String = "";
//URL = parse Value from XML;
fileArray.push(URL);
}
sendRequest();
}
private function sendRequest():void
{
getXMLFile.url = fileArray (count);
getXMLFile.send();
}
private function getPatient(event:ResultEvent):void
{
//If Success request for Next Patient
requestForNextPatient();
}
private function faultHandler(event:FaultEvent):void
{
//If fault request for Next Patient
requestForNextPatient();
}
private function requestForNextPatient():void
{
//Request for Next Patient
count++;
if(count > fileArray.length)
sendRequest():
}
]]>
</fx:Script>
<s:HTTPService id="getXMLFile" fault="faultHandler(event)" result="getPatient(event)" resultFormat="object" />
This may help you.....
I have a web application developed using flex and cakephp. My client need to make a desktop application of that web application using Adobe Air. The conversion of the flex to Air is done successfully. I the flex application the communication of flex and cakephp is handled using a remotes controller.
In air application I have a problem of authenticating the user with cakephp default user authentication. Can anyone help me to find a solution for this?
i suggest you to send your user credentials via POST to your cakephp backend.
A login function in your UsersController would look something like this:
public function login() {
if ($this->Auth->login()) {
$this->serviceResponse(Status::SUCCESS);
} else {
$this->serviceResponse(Status::AUTH_FAILED);
}
}
// this is just an example out of my appcontroller to send json responses
public function serviceResponse($code, $data = array()) {
$response = compact('code', 'data');
$this->response->body(json_encode($response));
$this->response->send();
$this->shutdownProcess();
exit;
}
// I also defined a class for return statuses
class Status {
const SUCCESS = 'success';
const ERROR = 'error';
...
}
Basically, you want to send the validation request as an ajax request. To do that you need to modify headers, capture session ids through cookies and post them to keep the session alive. It expects a JSON object returned from Cake.
I've created a couple Flex classes that achieve just this for a Flex Mobile App and a CakePHP backend. It should work the same for your needs.
It's in two files, the AutoValidationUrlRequest.as extends the HeaderURLRequest.as file. I'm not positive but there may be a couple variables to change, but overall it works very well and probably won't take more than a couple changes to get it working on your app.
To use it, simply create a new AutoValidationUrlRequest object and add an event listener on the headerUrlRequestComplete Event and then run AutoValidationUrlRequest.send(...) to POST. there is also a handy method called convertToPostVars for easy Cake Friendly Post variables.
AutoValidationUrlRequest.as:
package libs
{
import flash.events.Event;
import flash.events.EventDispatcher;
import flash.events.HTTPStatusEvent;
import models.LocalDeviceData;
import models.Model;
import mx.collections.ArrayCollection;
import mx.core.FlexGlobals;
import mx.utils.ObjectUtil;
[Event("LoginFailed")]
[Event("MobileUserDoesNotExist")]
public class AutoValidationURLRequest extends HeaderURLRequest
{
public static const LOGIN_FAILED:String = "LoginFailed";
public static const MOBILE_USER_DOES_NOT_EXIST:String = "MobileUserDoesNotExist";
/**
* will automatically be set by this class, if not set will login
*/
public var requestHeaders:Object = new Object();
private var _cookie:Object;
/**
* should be an object with name of the cookie variables parsed in as key/value pairs
*/
protected function set cookie(ck:Object):void{
_cookie = ck;
}
protected function get cookie():Object{
return _cookie;
}
public function AutoValidationURLRequest(){
};
public function send(url:String, postData:Object, generateUrlVars:Boolean = true):void{
if(generateUrlVars){
postData = convertToPostVars(postData);
}
sendRequest("http://yourwebsite.com"+url, postData, requestHeaders);
}
override protected function parseHeaders(e:HTTPStatusEvent):void{
super.parseHeaders(e);
if('Set-Cookie' in headers){
requestHeaders['Cookie'] = parseCookie(headers['Set-Cookie']);
//requestHeaders['User-Agent'] = headers['User-Agent'];
}
}
/**
* returns the cookie key/val string for send requests back to the server
*/
protected function parseCookie(cookieString:String):String{
var cookieObj:Object = new Object();
var cookieBits:Array = cookieString.split("; ");
return cookieBits[0];
/*
for each(var ck:String in cookieBits){
var cb:Array = ck.split("=");
cookieObj[cb[0]] = cb[1];
}
return cookieObj;
*/
}
}
}
HeaderURLRequest.as:
package libs
{
import flash.events.Event;
import flash.events.EventDispatcher;
import flash.events.HTTPStatusEvent;
import flash.net.URLLoader;
import flash.net.URLRequest;
import flash.net.URLRequestHeader;
import flash.net.URLRequestMethod;
import flash.net.URLVariables;
import mx.core.FlexGlobals;
import mx.rpc.events.ResultEvent;
import mx.utils.ObjectUtil;
[Event("headerUrlRequestComplete")]
public class HeaderURLRequest extends EventDispatcher
{
public static const HEADERURLREQUEST_COMPLETE:String = "headerUrlRequestComplete";
public var headers:Array = [];
public var data:Object = new Object();
public var variables:Object = new Object();
public var invalidFields:Object = new Object();
public var errorMsg:String = "";
/**
* the headers array must contain an object with a 'name' key and a 'value' key eg: cookie: <cookieStr>
*/
public function HeaderURLRequest():void{
}
public function sendRequest(url:String, postData:Object = null, requestHeaders:Object = null):void{
var urlLoader:URLLoader = new URLLoader()
var urlRequest : URLRequest = new URLRequest(url);
//make it an ajax request
urlRequest.requestHeaders.push(new URLRequestHeader('X-Requested-With', 'XMLHttpRequest'));
for(var header:* in requestHeaders){
var authHeader:URLRequestHeader = new URLRequestHeader(header as String, requestHeaders[header]);
urlRequest.requestHeaders.push(authHeader)
}
var urlVariables:URLVariables = new URLVariables();
for (var vars:* in postData){
urlVariables[vars] = postData[vars];
}
urlRequest.method = URLRequestMethod.POST
urlRequest.data = urlVariables;
urlLoader.addEventListener(Event.COMPLETE, getData);
urlLoader.addEventListener(HTTPStatusEvent.HTTP_RESPONSE_STATUS, parseHeaders);
urlLoader.load(urlRequest);
}
public function convertToPostVars(postData:Object, prependKeyName:String = ""):Object{
var params:Object = {};
if(prependKeyName == ""){
params['_method'] = 'POST';
}
for (var item:* in postData){
var objtype:Object = ObjectUtil.getClassInfo(postData[item]);
if(objtype.name == "Object"){
var modelKeyName:String = prependKeyName+"["+item+"]";
var subParams:Object = convertToPostVars(postData[item],modelKeyName);
params = merge(params, subParams);
}else{
params["data"+prependKeyName+"["+item+"]"] = postData[item];
}
}
return params;
}
public function flashErrorMsg():String{
var err:String = errorMsg;
errorMsg = "";
return err;
}
protected function parseHeaders(e:HTTPStatusEvent):void{
var i:Number=0;
headers = [];
for each(var header:URLRequestHeader in e.responseHeaders){
headers[header.name] = header.value;
i++;
}
}
protected function getData(e:Event):void{
//trace('data: ');
if(e.currentTarget.data == ''){
e.currentTarget.data = '{}';
}
data = JSON.parse(e.currentTarget.data);
//trace(ObjectUtil.toString(data));
if(data.hasOwnProperty('variables')){
variables = data.variables;
if (variables != null){
if(variables.hasOwnProperty('invalidFields')){
invalidFields = variables.invalidFields;
for (var error:String in invalidFields){
errorMsg += invalidFields[error] + "\n\n";
}
}
}else{
//no variable data found!!
}
}
dispatchEvent(new Event(HEADERURLREQUEST_COMPLETE));
}
public function isEmpty(obj:Object){
var isEmpty:Boolean = true;
for (var n in obj) { isEmpty = false; break; }
return isEmpty;
}
public function merge( obj0:Object, obj1:Object ):Object
{
var obj:Object = { };
for( var p:String in obj0 )
{
obj[ p ] = ( obj1[ p ] != null ) ? obj1[ p ] : obj0[ p ];
//trace( p, ' : obj0', obj0[ p ], 'obj1', obj1[ p ], '-> new value = ', obj[ p ] );
}
for (var p1:String in obj1){
if(!obj.hasOwnProperty(p1)){
obj[ p1 ] = obj1[ p1 ] ;
}
}
return obj;
}
}
}
Also, using this with my forked version of Jose Gonzalez's CakePHP ajax_controller plugin is really handy. It basically takes any Ajax Request and converts all view variables and outputs them into a JSON object, no rendered view. Otherwise, if you're not using an ajax request, Cake will render the views normally. Good Luck!
I know there are a number of posts dealing with this issue. But, I'm still not understanding it.
I keep getting a "1120: Access of undefined property CSSloader." in the following script:
package as3.comp{
import flash.events.Event;
import flash.events.ProgressEvent;
import flash.net.URLLoader;
import flash.net.URLRequest;
import flash.display.Loader;
import flash.display.MovieClip;
import flash.text.StyleSheet;
public class cont extends MovieClip {
public var contentWidth:Number;
public var contentHeight:Number;
private var myXML:XML;
private var myLoader:URLLoader;
public function cont():void {
//Start
}
public function start():void {
myTooltip.start();
myTooltip.followMouse(false);
myTooltip.hide();
myWaiting.start();
myWaiting.hide();
myXML = new XML();
myXML.ignoreComments=true;
myXML.ignoreWhitespace=true;
contentWidth=100;
contentHeight=100;
contentSpace.width=contentWidth;
contentSpace.height=contentHeight;
//myWaiting.hide(); //hide clock
}
public function loadMc(contentFile:String):void {
var pictLdr:Loader = new Loader();
var pictURL:String=contentFile;
var pictURLReq:URLRequest=new URLRequest(pictURL);
pictLdr.contentLoaderInfo.addEventListener(Event.COMPLETE, imgLoadedF);
pictLdr.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS, preloader);
pictLdr.load(pictURLReq);
contentLoadMC.addChild(pictLdr);
}
private function imgLoadedF(event:Event):void {
myTooltip.hide();
MovieClip(parent.parent).addContentMovie(this);
MovieClip(parent.parent).refresh();
}
private function preloader(event:ProgressEvent):void {
var pcent:Number=event.bytesLoaded/event.bytesTotal*100;
myTooltip.show(""+int(pcent));
}
public function loadCSS(event:Event):void {
var CSSloader:URLLoader = new URLLoader();
var req_css:URLRequest = new URLRequest("example.css");
CSSloader.load(req_css);
CSSloader.addEventListener("complete", loadXML);
}
public function loadXML(contentFile:String) {
var XML_URL:String=contentFile;
var myXMLURL:URLRequest=new URLRequest(XML_URL);
myLoader=new URLLoader(myXMLURL);
myLoader.addEventListener("complete", xmlLoaded);
}
private function xmlLoaded(event:Event):void {
myXML=XML(myLoader.data);
myXML.ignoreWhite = true;
var sheet:StyleSheet = new StyleSheet();
sheet.parseCSS(CSSloader.data);
myHtmlText.styleSheet = sheet;
myHtmlText.htmlText="HERE" + myXML.pageTop;
myHtmlText.width=contentWidth-10;
myHtmlText.height=myHtmlText.textHeight+30;
myHtmlText.x=10;
myHtmlText.y=10;
contentSpace.width=contentWidth;
contentSpace.height=myHtmlText.height+4;
myWaiting.hide();
MovieClip(parent.parent).addContentMovie(this);
MovieClip(parent.parent).refresh();
myLoader.removeEventListener("complete", xmlLoaded);
}
public function loadContent(contentFile:String) {
if (contentFile.substr(-3)=="xml") {
myWaiting.show();//show clock
loadXML(contentFile);
} else {
myTooltip.show("0");
loadMc(contentFile);
}
}
}
}
I've tried adding the code within loadCSS to both loadXML and xmlLoaded, but get the same error.
Any help would be GREATLY appreciated. Thanks.
You declared CSSloader in the function loadCSS, but you get the error in the function xmlloaded, which is a different scope. If you want CSSloader to be scoped for all functions, you'll have to declare it as a variable outside these functions - by convention at the top. (Unfortunately you have omitted the context of this code, but I assume this is inside a class?).