I have an issue with Workers in AIR : when I try to open a file in a non-primordial Worker, I get a Security error. When I try the same code in the primordial Worker, it works well.
I load another swf and pass its bytes when creating the second Worker.
First, I tried with URLLoader (code in 2nd worker) :
// Loading XML test
var loader:URLLoader = new URLLoader(new URLRequest('app:/config/generator/galaxy.xml'));
loader.addEventListener(Event.COMPLETE, function(evt:Event):void
{
// Trace
CEThreadDebugger.log(XML(loader.data).toString());
});
loader.addEventListener(IOErrorEvent.IO_ERROR, function(evt:IOErrorEvent):void
{
CEThreadDebugger.log(evt.text, CEThreadDebugger.ERROR);
});
loader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, function(evt:SecurityErrorEvent):void
{
CEThreadDebugger.log(evt.text, CEThreadDebugger.ERROR);
});
I get this error :
[LOG]ERROR->Error #2048: Security sandbox violation: app:/SombresCieux.swf cannot load data from app:/config/generator/galaxy.xml.
Then I tried with File :
var file:File = File.applicationDirectory.resolvePath('config/generator/galaxy.xml');
var stream:FileStream = new FileStream();
stream.open(file, FileMode.READ);
var xml:XML = XML(stream.readUTFBytes(stream.bytesAvailable));
stream.close();
And I get this error (my code is in _mainToWorker method) :
[LOG]INFO->Error #0 : SecurityError -> file
SecurityError: file
at flash.filesystem::File$/initAppResourceDir()
at flash.filesystem::File$/get appResourceDirectoryPath()
at flash.filesystem::File$/get applicationDirectory()
at generator::Generator/_mainToWorker()
at engine.generic.system.concurrency::CEThreadMain/Evt_mainToWorker()
I noticed that the error comes from this line alone :
var file:File = File.applicationDirectory.resolvePath('config/generator/galaxy.xml');
So it works in the primordial Worker (main app), but not in the threads...
Can't the Workers access system's files nor load any file ? It's a quite huge limitation...
Thanks for the replies !
public function createWorker(swf:ByteArray,
giveAppPrivileges:Boolean = false):Worker
giveAppPrivileges:Boolean (default = false) — indicates whether the worker should be given application sandbox privileges in AIR. This parameter is ignored in Flash Player
Related
I'm working on an application and we are using Flash to add an interface. During the initialize the app loads in a config file with references to image paths. When I use the Loader and URLRequest classes to load those images the path is not working and it's causing issues. Based on everything I've researched my code should work. I have a trace that outputs "source/icons/default.png" which is the correct relative path for the external image and loading the image works, but I need to use a variable to set the image path. Setting the URLRequest with a variable, new URLRequest("source/icons/" + default.png);, causes it use a full file path that looks wrong and reports a 2035 error. Is there something that I'm doing wrong? I'm not sure what to do at this point. I've verified the file exists and I've verified the path of the file.
Trace Ouput:
source/icons/default.png
Error Output:
[CompanionStatus] Error occurred while loading bitmap
[CompanionStatus] 2035 : Error #2035: URL Not Found. URL: file:///C|/Users/devtrooper/Desktop/project/source/icons/default.png
It looks like flash is replacing the colon (:) near the drive letter with a pipe (|) and I'm not sure if that is the issue.
Here is my method for loading images:
private function getBitmapData(nameString:String, imagePath:String):void{
try{
var bitmapDataFunction:Function = addBitmapDataToDictionary(nameString);
var path:String = ICON_FOLDER_PATH + imagePath;
var loader:Loader = new Loader();
var urlRequest:URLRequest = new URLRequest("source/icons/" + imagePath);
trace("URLRequest.url " + urlRequest.url);
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, bitmapDataFunction, false, 0, true);
loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, handleBitmapDataError, false, 0, true);
loader.load(urlRequest);
} catch (e:Error) {
log("Error occured while trying to load image data");
log(e.name + " : " + e.message);
}
}
you can use File method instead of urlRequest method like this:
var urlPath:String="";
var picFile:File = File.desktopDirectory.resolvePath("source/icons/default.png");//you can use applicationDirectory,applicationStorageDirectory,userDirectory,doumenntDirectory and ...
if (picFile.exists == true) {
urlPath = picFile.url;
}
In my tablet app I download files from the server and I try to save these files to my application storage directory. Then I get an error which says:
Error #2044: Unhandled IOErrorEvent:. text=Error #2038: File I/O Error.
It is occuring on this line:
var fileStream:FileStream = new FileStream();
Maybe some files are corrupted on the server but I can influence this. I tried to catch the error, but this isn't working. What do I do wrong?
The complete code
try {
var file:File = File.desktopDirectory.resolvePath(_path);
var fileStream:FileStream = new FileStream();
fileStream.openAsync(file, FileMode.WRITE);
var fileData:ByteArray = new ByteArray();
_urlStream.readBytes(fileData, 0, _urlStream.bytesAvailable);
fileStream.writeBytes(fileData,0,fileData.length);
fileStream.close();
} catch(error:Error) {
// do something
}
My program has an export / import function that uses AS3Commons3-zip to make zipfiles of some content (pictures, small videos, small pdf's) inside the program. User selects an topic to make the zipfile out of, selects save location, program copies the files to tempDir (with File.createTempDirectory method) and then it loops through the tempDir with following code:
public function fileSelected(event:Event):void{
zipFile = event.currentTarget as File;
addFileToZip(tempDir, zip);
}
public function addFileToZip(file:File, zip:Zip, path:String=""):void{
if(file.isDirectory){
var directory:Array = file.getDirectoryListing();
filesToCompress = filesToCompress + directory.length;
dispatchEvent(new
for each (var f:File in directory){
addFileToZip(f, zip, path + "/" + file.name);
}
fileAddedToZip();
}else{
file.addEventListener(Event.COMPLETE, function():void{
var pathSplit:Array = file.nativePath.split(".tmp\\",2);
var fileNamePath:String = pathSplit[1] as String;
zip.addFile(fileNamePath, file.data);
fileAddedToZip();
});
file.addEventListener(ProgressEvent.PROGRESS, function(e:ProgressEvent):void{
totalLoaded = totalLoaded+e.bytesLoaded;
trace(totalLoaded+" <---TOTAL LOADED");
});
file.load();
}
}
public function fileAddedToZip():void{
filesCompressed++;
if (filesToCompress == filesCompressed){
var stream:FileStream = new FileStream();
stream.open(zipFile, FileMode.WRITE);
zip.serialize(stream);
stream.close();
tempDir.deleteDirectoryAsync(true);
}
}
And the code itself seems to work fine: the zip files import and export perfectly fine. Problem is that the program crashes at seemingly random times. Sometimes it goes through with 30 files, sometimes it crashes with 3. Sometimes it manages to make the same zip from same files 3 times in a row, then it crashes on the fourth try on some file and fifth try crashes on different file.
For example: Five tries with 35 copies of same image exported into the zip:
35/35, TOTAL LOADED trace: 3110337
35/35, TOTAL LOADED trace: 3110337
CRASH, TOTAL LOADED trace: 0 after initializing 26 files
35/35, TOTAL LOADED trace: 3110337
35/35, TOTAL LOADED trace: 3110337
CRASH, TOTAL LOADED trace: 0 after initializing 14 files
CRASH, crashed initializing first file
35/35, TOTAL LOADED trace: 3110337
35/35, TOTAL LOADED trace: 3110337
FREEZE WITH NO CRASH (stuck on file 17/35, cancel button works etc.), TOTAL LOADED trace: 1282932
I can see no pattern with it. File.load() method seems to be the culprit but no idea why. Crashes throw no errors at all. Only thing that is certain is that more the image sizes are in total (still under 100MB) the crashes are more common. Any ideas?
Solved this by using URLLoader instead:
var request:URLRequest = new URLRequest(file.nativePath);
var urlLoader:URLLoader = new URLLoader(request);
urlLoader.addEventListener(Event.COMPLETE, function (event:Event):void {
var pathSplit:Array = file.nativePath.split(".tmp\\",2);
var fileNamePath:String = pathSplit[1] as String;
zip.addFile(fileNamePath, event.target.data);
fileAddedToZip();
});
urlLoader.dataFormat = URLLoaderDataFormat.BINARY;
urlLoader.load(request);
I want to cache the response of a urlRequest for offline usage in Adobe Air. When I compile for flash player the cache works and I get the response even when I disconnect the network, but when I compile for Adobe Air I get error. PS: useCache and cacheResponse dose not work!
stage.addEventListener(MouseEvent.CLICK , callReq)
var loader:URLLoader = new URLLoader()
function callReq(e:Event):void
{
//URLRequestDefaults.manageCookies = true;
//URLRequestDefaults.useCache = true;
var r:String = "http://onecom.no/presentation_json.php?what=get_slides&slide_id[]=2540"
var urlRequest:URLRequest = new URLRequest(r)
// urlRequest.cacheResponse = true
// urlRequest.useCache = true
urlRequest.url = r
loader.addEventListener(Event.COMPLETE , Comp)
loader.load(request)
}
function Comp(e:Event):void
{
trace( e.target.data)
}
Air can not use the browsers cache. I had to build my own cache class that saves all URLRequest responses to a Shared Object and loads them if there is no internet connection
save them to variables and store them in the local SQLlite database on your device/computer?...
Using local SQLlite on device
I am trying to upload a file to the server. I'm doing it like this:
var fileRef:FileReference = new FileReference();
fileRef.addEventListener(flash.events.Event.SELECT, selectHandler);
fileRef.addEventListener(flash.events.Event.COMPLETE, completeHandler);
fileRef.addEventListener(ProgressEvent.PROGRESS, normalprogressHandler);
fileRef.browse();
function selectHandler(event:flash.events.Event):void
{
var params:URLVariables = new URLVariables();
params.date = new Date();
params.ssid = "94103-1394-2345";
var request:URLRequest = new URLRequest("http://www.test.com/Uploads");
request.method = URLRequestMethod.POST;
request.data = params;
fileRef.upload(request, "Custom1");
}
function completeHandler(event:flash.events.Event):void
{
trace("uploaded");
}
function normalprogressHandler(event:ProgressEvent):void
{
var percent:Number = Math.floor((event.bytesLoaded * 100)/ event.bytesTotal );
trace(percent+"%");
}
Would it be possible to upload a file but without browsig for it? I want to decide myself what file to upload instead of the user performing a browse first
You can't do that with FileReference which has the following limitations (reference):
The load() and save() APIs can only be called in response to user
interaction (such as a button click).
The locations of the loaded and save files are not exposed to
ActionScript.
The APIs are asynchronous (non-blocking).
Clearly, it would represent a major security risk if the Flash player was arbitrarily allowed to upload anything from your local file system to a remote server.
If you're trying to upload from an AIR app, you can do what you're trying to do with the File class.