save image in a directory in applicationStorageDirectory - actionscript-3

I was trying to save an imagefile to a directory in applicationStorageDirectory of my air project. Created the directory first
var imageDirectory:File = File.applicationStorageDirectory.resolvePath("vispics");
if (imageDirectory.exists)
{
Alert.show("Directory Already Exists");
}
else {
imageDirectory.createDirectory();
Alert.show(imageDirectory.nativePath);
}
The next part is saving image from my cam right now it saves to the applicationStorageDirectory. Here is how i do it
var randInt:int = Math.random() * (99999 - 1001) + 1001;
var randStr:String = randInt.toString();
var filename:String = ""+randStr+".jpg";
var file:File = File.applicationStorageDirectory.resolvePath( filename );
var wr:File = new File( file.nativePath );
var stream:FileStream = new FileStream();
stream.open( wr , FileMode.WRITE);
stream.writeBytes ( imageData, 0,imageData.length );
stream.close();
Is there a way that i can store the image in my "vispics" directory?
Thanks in advance.

Try:
var file:File = File.applicationStorageDirectory.resolvePath("vispics/" + filename);

Related

How do I write a huge bytearray to file progressively and avoid that dreaded memory error

I'm working on an Air project that downloads huge (zip) files, then unzips them and finally deletes the original .zip file it downloaded.
Everything's running smoothly except when I want to write the unzipped file to disk.
Trouble is, I keep running into the issue of this little monster of an error.
Error: Error #1000: The system is out of memory.
Here's the part of the code that is giving me grief. This works perfectly when the file is small (tested on a 3 MB file) but as soon as I try one of my large files (458 MB), I get the error.
private function unzipFile()
{
var pulledFile:FZipFile;
var index:int = 0;
var chunkSize:int = 1000000;
Console.log("Unzipping file...");
var zip:FZip = new FZip();
zip.addEventListener(Event.COMPLETE, onUnzipComplete);
var fileStream:FileStream = new FileStream();
zip.load(new URLRequest(urlToUnzip));
function onUnzipComplete(e:Event)
{
pulledFile = zip.getFileAt(0);
var file:File = File.documentsDirectory.resolvePath(pulledFile.filename);
fileStream.openAsync(file, FileMode.WRITE);
writeChunk();
}
function writeChunk()
{
var bytesToGet:int = pulledFile.content.bytesAvailable;
if (bytesToGet > chunkSize)
bytesToGet = chunkSize;
Console.log("Writing chunk " + (int((pulledFile.content.length - pulledFile.content.bytesAvailable) / chunkSize) + 1) + " of " + (int(pulledFile.content.length / chunkSize) + 1));
var fileData:ByteArray = new ByteArray();
pulledFile.content.readBytes(fileData, 0, bytesToGet);
fileStream.writeBytes(fileData, 0, fileData.length);
if (index < pulledFile.content.bytesAvailable)
{
writeChunk();
index += bytesToGet;
}
else
{
fileStream.close();
Console.log("Unzipping complete");
}
}
}
The code crashes specifically on the line
var bytesToGet:int = pulledFile.content.bytesAvailable;
How do I still progressively write content to a file without knowing how many bytes are available to me? If I don't have access to the bytesAvailable property, how do I know I'm done writing?
I'm using the FZip library for decompression.
This was tough, but I figured it out. The trick is to use the "serialize" method of the FZip and avoid touching the properties of the content ByteArrayaltogether.
Here's the final code that works.
private function unzipFile()
{
var pulledFile:FZipFile;
Console.log("Decompressing file...");
var zip:FZip = new FZip();
zip.addEventListener(Event.COMPLETE, onUnzipComplete);
var fileStream:FileStream = new FileStream();
zip.load(new URLRequest(urlToUnzip));
function onUnzipComplete(e:Event)
{
pulledFile = zip.getFileAt(0);
var file:File = File.documentsDirectory.resolvePath("Easywatch/" + pulledFile.filename);
fileStream.open(file, FileMode.WRITE);
zip.serialize(fileStream, false);
fileStream.close();
Console.log("Decompression complete");
}
}

zip file contents have no data

I have for a while been trying to make a zipping script.
The closest I have come to what I am needing is this one.
import flash.filesystem.File;
import flash.events.Event;
import FZIP.*;
var directory:File = File.desktopDirectory.resolvePath("Test File");
var zip:FZip = new FZip();
var files:Array = directory.getDirectoryListing();
for(var i:uint = 0; i < files.length; i++)
{
var file_2:File = new File(files[i].nativePath);
// zip.addFile(file_2.name, file_2.data);
zip.addFile(file_2.name, ba);
trace(file_2.name);
trace(files[i].nativePath);
trace(file_2.data);
trace(file_2.size);
}
var ba:ByteArray = new ByteArray();
zip.serialize(ba);
ba.position = 0;
var finalZIP:File = File.desktopDirectory.resolvePath("TEST.zip");
var fs:FileStream = new FileStream();
fs.open(finalZIP, FileMode.WRITE);
fs.writeBytes(ba);
trace("BA POS: "+ba.position);
fs.close();
The problem is that all files are without data (have no size).
I don't use FZIP but since you got no answer I checked around and it seems the correct usage would be something like this below (or at least get you closer)..
import flash.filesystem.File;
import flash.events.Event;
import FZIP.*;
import FZIP;
var directory:File = File.desktopDirectory.resolvePath("Test File");
var files:Array = directory.getDirectoryListing();
var zip:FZip = new FZip();
var fs:FileStream;
var temp_BA:ByteArray = new ByteArray(); //general use and recycle
var fileCount:int = 1; //for file count as file name (assumes 1 file at least)
var temp_Str:String = ""; // a temp String to hold a file's name before adding it to ZIP
var extension_Str : String = ""; //set file extension placed inside the ZIP
for(var i:uint = 0; i < files.length; i++)
{
//# reseting for each iteration of the FOR loop
temp_BA.clear(); fs = new FileStream();
//# add file's bytes into a byte array
var file_2:File = new File(files[i].nativePath);
fs.open(file_2, FileMode.READ);
fs.readBytes( temp_BA ); //temp_BA now holds file content as byte array
//temp_BA.writeBytes( fs ); //is faster than readbytes method if can be done
//# (1) If this line you had before works for you, keep it
//zip.addFile(file_2.name, temp_BA); //addFile needs the content byte array and a name for it
//# (2) or use try like this below version instead (1) above
extension_Str = "jpg" ; //or get String from actual file extension on disk
temp_Str = "file" + String(fileCount) + "." + extension_Str; //eg: makes temp_Str = "file1.jpg"
zip.addFile( temp_Str, temp_BA); //make ZIP contain a file-name [temp_Str] & file-data is from [temp_BA]
fs.close();
fileCount++; //increment by one
}
//var finalZIP:File = File.desktopDirectory.resolvePath("TEST.zip");
var finalZIP:File = File.applicationStorageDirectory;
finalZIP = finalZIP.resolvePath("TEST.zip");
var fs:FileStream = new FileStream();
fs.open(finalZIP, FileMode.WRITE);
zip.serialize(fs); //generate ZIP file data
fs.close();

AS3/AIR: IOStream Error when trying to upload files

I'm making an AIR app in which the user drags and drops image files onto the stage, the app then uploads those dropped images to the site imgur.com, and then returns with links to the images (in XML format).
I am having two issues:
the program works successfully with a very small file, however anything larger (1mb or more), I get an IOStream error 2023. Imgur supports uploads of up to 10mb so I know it must be something on my end.
I would like to be able to drop multiple image files at once into the program, and have it upload all of them (either synchronously or asynchronously, it does not matter). Right now the program gives errors when I attempt to do this (something along the lines of the byteArray having to be greater than 0).
Below is the code in question which is giving me issues. (thank you for your help in advanced)
private function doDragDrop(e:NativeDragEvent):void
{
trace("doDragDrop() called.");
var dropFiles:Array = e.clipboard.getData(ClipboardFormats.FILE_LIST_FORMAT) as Array;
for each (var file:File in dropFiles)
{
switch (file.extension.toLowerCase())
{
case "jpg" :
case "jpeg" :
case "gif" :
case "png" :
case "apng" :
case "tiff" :
case "bmp" :
case "pdf" :
case "xcf" :
trace("file Extension Check = passed");
addImage(file.nativePath);
break;
//error handling for non-supported filetypes
default :
trace("ERROR: Unsupported File Type Detected!");
}
}
}
private function addImage(nativePath:String):void
{
trace("addImage() called.");
trace("NativePath is: " + nativePath);
//var file:File = new File(nativePath);
var file:File = File.desktopDirectory.resolvePath(nativePath);
var ba:ByteArray = new ByteArray();
var stream:FileStream = new FileStream();
stream.open(file, FileMode.READ);
stream.readBytes(ba);
stream.close();
var loader:Loader = new Loader();
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, fileLoaded);
loader.loadBytes(ba);
}
private function fileLoaded(e:Event):void
{
trace("fileLoaded() called.");
var bitmap:Bitmap = Bitmap(e.target.content);
var bitmapData:BitmapData = bitmap.bitmapData;
var png:ByteArray = PNGEncoder.encode(bitmapData);
urlLoader = new URLLoader();
urlLoader.dataFormat = URLLoaderDataFormat.VARIABLES;
urlLoader.addEventListener(Event.COMPLETE, onCookieSent);
urlLoader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, onSecurityError);
urlLoader.addEventListener(IOErrorEvent.IO_ERROR, onIOError);
var vars:String = "?key=" + API_KEY + "&name=name&title=title";
var request:URLRequest = new URLRequest(UPLOAD_URL + vars);
request.contentType = "application/octet-stream";
request.method = URLRequestMethod.POST;
request.data = png;
urlLoader.load(request);
}
private function onCookieSent(e:Event):void
{
trace("onCookieSent() called.");
var res:XML = new XML(unescape(urlLoader.data));
var resultsList:XMLList = res.links;
trace(resultsList);
}
private function onIOError(e:IOErrorEvent):void
{
trace("ioErrorHandler: " + e);
TweenLite.to(tv_mc, 2, {alpha:0.5, scaleX:1.0, scaleY:1.0, ease:Elastic.easeOut});
// Handle error
}
private function onSecurityError(e:SecurityErrorEvent):void
{
trace("securityErrorHandler: " + e);
TweenLite.to(tv_mc, 2, {alpha:0.5, scaleX:1.0, scaleY:1.0, ease:Elastic.easeOut});
// handle error
}
//When the dragged object leaves the drop point, do this
private function doDragExit(e:NativeDragEvent):void
{
trace("doDragExit() called.");
TweenLite.to(tv_mc, 2, {alpha:0.5, scaleX:1.0, scaleY:1.0, ease:Elastic.easeOut});
}
after doing this:
var ba:ByteArray = new ByteArray();
var stream:FileStream = new FileStream();
stream.open(file, FileMode.READ);
stream.readBytes(ba);
stream.close();
you already have a ByteArray of the file/image. can't you just send this one...
private function addImage(nativePath:String):void
{
trace("addImage() called.");
trace("NativePath is: " + nativePath);
//var file:File = new File(nativePath);
var file:File = File.desktopDirectory.resolvePath(nativePath);
var ba:ByteArray = new ByteArray();
var stream:FileStream = new FileStream();
stream.open(file, FileMode.READ);
stream.readBytes(ba);
stream.close();
urlLoader = new URLLoader();
urlLoader.dataFormat = URLLoaderDataFormat.VARIABLES;
urlLoader.addEventListener(Event.COMPLETE, onCookieSent);
urlLoader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, onSecurityError);
urlLoader.addEventListener(IOErrorEvent.IO_ERROR, onIOError);
var vars:String = "?key=" + API_KEY + "&name=name&title=title";
var request:URLRequest = new URLRequest(UPLOAD_URL + vars);
request.contentType = "application/octet-stream";
request.method = URLRequestMethod.POST;
request.data = ba;
urlLoader.load(request);
}

Adobe AIR - Save image on hard drive

I found the below snippet to save an image to a specific folder with Adobe AIR.
How to modify it that the "Save As" OS-window comes up first? (So users can choose where to save the image on the hard-drive)
var arrBytes:ByteArray = PNGEncoder.encode(bmd);
var file:File = File.desktopDirectory.resolvePath(folderName + "/" + fileName + fileNum + ".png");
var fileStream:FileStream = new FileStream();
//
fileStream.open(file, FileMode.WRITE);
fileStream.writeBytes(arrBytes);
fileStream.close();
Thanks.
Use File.browseForSave:
import flash.filesystem.*;
import flash.events.Event;
import flash.utils.ByteArray;
var imgBytes:ByteArray = PNGEncoder.encode(bmd);
var docsDir:File = File.documentsDirectory;
try
{
docsDir.browseForSave("Save As");
docsDir.addEventListener(Event.SELECT, saveData);
}
catch (error:Error)
{
trace("Failed:", error.message);
}
function saveData(event:Event):void
{
var newFile:File = event.target as File;
if (!newFile.exists) // remove this 'if' if overwrite is OK.
{
var stream:FileStream = new FileStream();
stream.open(newFile, FileMode.WRITE);
stream.writeBytes(imgBytes);
stream.close();
}
else trace('Selected path already exists.');
}
The manual is always your friend :)
BTW, I see you're relatively new here - welcome to StackExchange! If you find my answer helpful, please be sure to select it as the answer.

Object Data Type in AS3 and Flash Builder 4.5.1

I am trying to save a Sprite object as a file on the device I'm working on and it seems to work. the problem I'm having is reading the saved file back and placing it back on stage as a sprite. Below is the code I have so far, could someone tell me what it is I'm doing wrong? I have a suspicion that the saved isn't what I expect it to be since the file sizes have been under a kilobyte.
public function save_album(e:Event):void
{
var outFile:File = File.documentsDirectory; // dest folder is desktop
outFile = outFile.resolvePath("canvas3.bin");
var fs:FileStream = new FileStream();
var bytes:ByteArray = new ByteArray();
//trace (File.documentsDirectory.url + "/canvas2.bin");
fs.open(outFile, FileMode.WRITE);
bytes.writeObject(graffitiContainer) //graffitiContainer is a Sprite
bytes.position = 0;
fs.writeBytes(bytes, 0, bytes.length);
fs.close();
}
public function open_album(e:Event):void
{
var inBytes:ByteArray = new ByteArray();
var inFile:File = File.documentsDirectory;
inFile = inFile.resolvePath("canvas3.bin"); // name of file to read
var inStream:FileStream = new FileStream();
inStream.open(inFile, FileMode.READ);
inStream.readBytes(inBytes, 0, inBytes.length);
inStream.close();
inBytes.position = 0;
ui.removeChild(graffitiContainer);
var obj:Sprite = inBytes.readObject() as Sprite; //returns a null
graffitiContainer = obj;
ui = new UIComponent();
graffitiContainer.x = 0;
graffitiContainer.y = 100;
ui.addChild(graffitiContainer);
}
Not fully sure I understand what you're trying to accomplish; however, this implementation doesn't do what you're thinking - writeObject could only serialize general public properties, and not the graphics member.
You could render it to a Bitmap.
Saw a blog post about this:
http://jacwright.com/201/serializing-display-objects/