How can you save out a String into a file in AS3? - apache-flex

I have a string the user has typed and I want to save it into a file on the users harddrive. Can you do that? And if so, how?

Yes you can, with FileReference.
This is basically how it's done:
var bytes:ByteArray = new ByteArray();
var fileRef:FileReference=new FileReference();
fileRef.save("fileContent", "fileName");
Doesn't look too hard, does it?
And here's a video-tutorial on it too:
http://www.gotoandlearn.com/play?id=76
And the documentation:
http://livedocs.adobe.com/flash/9.0/ActionScriptLangRefV3/
Hope that helps.

Since I had a function to output bytes to a file (because I was doing something with bitmaps), I reused it to output a string as well, like this:
var filename:String = "/Users/me/path/to/file.txt";
var byteArray:ByteArray = new ByteArray();
byteArray.writeUTFBytes(someString);
outFile(filename, byteArray);
private static function outFile(fileName:String, data:ByteArray):void {
var outFile:File = File.desktopDirectory; // dest folder is desktop
outFile = outFile.resolvePath(fileName); // name of file to write
var outStream:FileStream = new FileStream();
// open output file stream in WRITE mode
outStream.open(outFile, FileMode.WRITE);
// write out the file
outStream.writeBytes(data, 0, data.length);
// close it
outStream.close();
}

In addition, you must have Flash Player 10 and a Flex Gumbo SDK installed in your Flex Builder 3.
You can also have a look the following example:
http://blog.flexexamples.com/2008/08/25/saving-files-locally-using-the-filereference-classs-save-method-in-flash-player-10/

In Flex 3 no you can't do it unless you upload the file to the server and then download the file via a url to the desktop.
In Air or Flex 4 you can save it directly from the application to the desktop as detailed above.

Related

Returning Multiple Files from MVC Action

So I've got an MVC 3 application that has a couple places where a text file gets generated and returned in an action using:
return File(System.Text.Encoding.UTF8.GetBytes(someString),
"text/plain", "Filename.extension");
and this works fabulously. Now i've got a situation where I'm trying to return a pair of files in a similar fashion. On the view, i have an action link like "Click here to get those 2 files" and i'd like both files to be downloaded much like the single file is downloaded in the above code snippet.
How can I achieve this? Been searching around quite a bit and haven't even seen this question posed anywhere...
Building on Yogendra Singh's idea and using DotNetZip:
var outputStream = new MemoryStream();
using (var zip = new ZipFile())
{
zip.AddEntry("file1.txt", "content1");
zip.AddEntry("file2.txt", "content2");
zip.Save(outputStream);
}
outputStream.Position = 0;
return File(outputStream, "application/zip", "filename.zip");
Update 2019/04/10:
As #Alex pointed out, zipping is supported natively since .NET Framework 4.5, from JitBit and others:
using (var memoryStream = new MemoryStream())
{
using (var archive = new ZipArchive(memoryStream, ZipArchiveMode.Create, true))
{
var file1 = archive.CreateEntry("file1.txt");
using (var streamWriter = new StreamWriter(file1.Open()))
{
streamWriter.Write("content1");
}
var file2 = archive.CreateEntry("file2.txt");
using (var streamWriter = new StreamWriter(file2.Open()))
{
streamWriter.Write("content2");
}
}
return File(memoryStream.ToArray(), "application/zip", "Images.zip")
}
Sorry for bumping an old question but...
Another alternative would be to initiate multiple file downloads using JavaScript, and serve files in two different Action Methods on ASP.NET's side.
You're saying you have a link:
On the view, i have an action link like "Click here to get those 2
files"
So make this link like this:
Click to get 2 files
<script src="download.js"></script>
I'm using download.js script found here but you can find plenty of different other options, see this SO question: starting file download with JavaScript for example
I would advice to create a zip file to include both the files using steps(ALGORITHM):
Create a Zip file and add the desired files into the zip
Return the zip file having all desired files from the action
Java Syntax (Just for understanding)
FileOutputStream fos = new FileOutputStream("downloadFile.zip");
ZipOutputStream zos = new ZipOutputStream(new BufferedOutputStream(fos));
zos.putNextEntry(new ZipEntry("Filename1.extension"+));
//write data in FileName1.extension
zos.write(contentBuffer1, 0, len);
zos.putNextEntry(new ZipEntry("Filename2.extension"));
//write data in FileName2.extension
zos.write(contentBuffer2, 0, len);
//write other files.....
zos.close();
Once zip file is created, return the newly created zip file to download.
return File("downloadFile.zip");
.DOT Net Equivalent using DotNetZip
var os = new MemoryStream();
using (var zip = new ZipFile())
{
//write the first file into the zip
zip.AddEntry("file1.txt", "content1");
//write the second file into the zip
zip.AddEntry("file2.txt", "content2");
//write other files.....
zip.Save(os);
}
outputStream.Position = 0;
return File(outputStream, "application/zip", "filename.zip");
Hope this helps!
Look at this SO solution: MVC Streaming Zip File
The advantage of this solution is that it streams the file to the client.
I just implemented this solution a couple of days ago and it worked fantastic.

Is it possible to load a local file without having to ask the user to browse to it first in an AIR Application?

I'm writing a small application for myself and instead of using a database I'd like to just use Excel to store the small amount of data I have on my local file system. I want to be able to load that data without having to use the typical FileReference browse() method as it would just be annoying to do every time I use the application.
The code below seems to find the file fine as the file.exists method below and most of the other attributes seem to be correct but the file.data is always null.
I'm guessing this is a security issue and that's why I'm running into this problem but I thought I'd ask and see if there is in fact a way around this problem.
var file:File = new File(fullPath + "\\" + currentFolder + ".txt");
if(file.exists) {
var byteArray:ByteArray = file.data;
}
If you want to read the content of a file, use the following code:
var stream:FileStream = new FileStream();
stream.open("some path here", FileMode.READ);
var fileData:String = stream.readUTFBytes(stream.bytesAvailable);
trace(fileData);
The data property is inherited from FileReference class and it will be populated only after a load call (see this link).
You're close, you just need to combine that with a FileStream object
var fileStream:FileStream = new FileStream();
fileStream.open(file, FileMode.READ);
var str:String = fileStream.readMultiByte(file.size, File.systemCharset);
trace(str);
more info here

Flex 3 & Air 2: Automatically detect when files on a directory are updated

A crazy idea just dropped from the sky and hit me in the head xD. I was wondering if it is possible to make and App capable of listening when the user "adds" new files to a directory.
Example:
The User opens up our Application.
The user adds new files on the desktop (using the Microsoft Explorer).
Our application automatically detects that new files have been added and executes a function or whatever.
Sound interesting right?
Maybe, this could be done using a programming language like Visual Basic and open the executable with the NativeProcess api and listen for an stdOut event... (:
Anyone got and idea to share with us? :)
Thanks
Lombardi
AIR can handle this natively...
the FileSystemList class fires an event directoryChange whenever a file in the watched directory changes.
You can even use it to watch for drives being mounted (I think Christian Cantrell showed that one off)
Ok, I think I'm getting closer, check out this solution! :)
private var CheckDelay:Timer = new Timer(5000, 0);
private function InitApp():void
{
CheckDelay.addEventListener(TimerEvent.Timer, CheckForNewFiles, false, 0, true);
CheckDelay.start();
}
private function CheckForNewFiles(event:TimerEvent):void
{
var FS:FileStream = new FileStream();
var Buffer:File = File.applicationStorageDirectory.resolvePath("FilesBuffer.cmd");
FS.open(Buffer, FileMode.Write);
FS.writeUTFBytes("cd " + File.desktopDirectory.nativePath + "\r\n" +
"dir /on /b > " + File.applicationStorageDirectory.resolvePath("FileList.txt").nativePath);
FS.close();
var Process:NativeProcess = new NativeProcess();
var NPI:NativeProcessStartupInfo = NativeProcessStartupInfo(); // What a large name! xD
NPI.executable = Buffer;
Process.start(NPI);
Process..addEventListener(NativeProcessExitEvent.EXIT, ReadFileList, false, 0, true);
}
private function ReadFileList(event:Event):void
{
var FS:FileStream = new FileStream();
var Buffer:File = File.applicationStorageDirectory.resolvePath("FilesBuffer.cmd");
FS.open(Buffer, FileMode.Read);
var FileData:String = FS.readUTFBytes(FS.bytesAvailable);
FS.close();
var FileArray:Array = FileData.split("\r\n");
var TempArray:ArrayCollection = new ArrayColletion();
var TempFile:File;
for(var i:int = 0;i<FileArray.length;i++){
TempFile = new File(FileArray[i]);
TempArray.addItem(TempFile);
}
}
At the end we got an Array (TempArray) that we could use on a datagrid (for example) with colums like: "extension, File Name, FilePath, etc.."
The files are updated every 5 seconds.
And, why we use all that code instead of a simple "File.getDirectoryListing()"? Because we are updating our application every 5 seconds, if why use getDirectoryListing(), our application will take much more RAM and also, the cmd command is much faster... :)
If you have a better idea, please share it with us! Thank you! :D
1 excellent solution for Windows: use Visual Studio, build the .net app found here http://msdn.microsoft.com/en-us/library/system.io.filesystemwatcher.aspx
In Adobe AIR use the native process to listen for change events dispatched by .net

Open a file in flex 3

How can I create a .txt file using flex 3? And I want to write some datas in to this file...... Is it possible? Any one can help me?
Thanks in advance..
Nimmy
//set File object
var file:File=File.documentsDirectory;
file=file.resolve(“myFile.txt”);
//set Stream object
var stream:FileStream=new FileStream();
//set FileMode
stream.open(file, FileMode.READ);
var data:String= stream.readUTFBytes(Stream.bytesAvailable);
//close file
stream.close();
different FILEMODE:
FileMode.APPEND: write only, append
new data to the bottom of the file;
FileMode.READ: read only, file must exist;
FileMode.UPDATE: both read / write the
data where positioned where you want;
FileMode.WRITE: write only , if file
doesn't not exist, will be created
otherwise will be overwritten;

how to download files to a default dir without poping an option window in Flex/Air?

I'm writing a app with Flex/air,and i need a function that downloading files to the default dir without a pop-up window.i tried to use ftp instead of http but found it's not supported by air.how can i solve this problem?
This should be possible in AIR. I don't know if there's a direct API approach, but you should be able to load the bytes into memory and then flush them into a file. In pseudo-pseudo-code using File and FileStream:
// get the bytes
var loader:URLLoader = new URLLoader();
loader.load("http://www.stackoverflow.com");
...
var bytes:ByteArray = loader.data;
// get the file in the correct location
var f:File = File.documentsDirectory.resolvePath("myfile.txt");
// write the file
var fs:FileStream = new FileStream(f, FileMode.WRITE);
fs.writeBytes(bytes);
fs.close();
There are a few examples out there to look at.
None of this is possible in Flash Player because of the security limits #viatropos suggests.
I don't think you can do that as it's a Security violation. The user must be prompted with a download window so they can choose the directory. I think the thinking goes "if you don't prompt the user, then a Flash/Flex app could download a bunch of junk to their computer without their permission", and that would make adobe look bad :/. I wish you could though.
You can, however, download it using a server side script without asking the user for permission. I do that with ruby to accomplish what you're describing.
Hope that helps,
Lance
You can but only air version because you have to use FileStream
var ff:File = File.desktopDirectory.resolvePath("sample.dwg");
var u:String = obj_l.d1.selectedItem.data + "" + obj_l.d2.selectedItem.label;
var ll3:URLLoader = new URLLoader ();
u = GETURL() + u;
rr.url = u;
//ff.download(rr);
ll3.dataFormat = URLLoaderDataFormat.BINARY;
ll3.load(rr);
ll3.addEventListener(Event.COMPLETE , function (e:Event):void {
var stream:FileStream = new FileStream ();
stream.open(ff,FileMode.WRITE);
stream.writeBytes(ll3.data);
});

Resources