Update xml file node attribute in actionscript - actionscript-3

We need to modify/update the xml attribute of .idms file. using actionscript. I'm using below approach to do that.
protected function windowedapplication1_creationCompleteHandler(event:FlexEvent):void
{
var file:File = File.desktopDirectory.resolvePath('myInputFile.xml');
var fileStream:FileStream = new FileStream();
fileStream.open(file, FileMode.READ);// doesn't read processing instrunction
var xml:XML = new XML(fileStream.readUTFBytes(fileStream.bytesAvailable));
fileStream.close();
var writeStream:FileStream = new FileStream();
writeStream.open(file, FileMode.WRITE);
for each(var node:XML in xml.descendants("*"))
{
if(node.localName() == "Link")
{
var linkfile:String=node.#LinkResourceURI = "file:/Shared/Logos/Bk.ai";
}
}
writeStream.writeUTFBytes(String(xml));
writeStream.close();
}
In above code problem is that it does not read processing instruction on top of xml file. in result after writing the xml file, it won't read the file as InDesign snippet file anymore.
Processing instrunctions are:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
Can anyone help me in figure out how I can I read the processing instrunction as well in new file ?
Thanks for quick reply but Even though I've made this property as flase it's keep ignoring the processing instuction.
var file:File = File.desktopDirectory.resolvePath('031413115849909.idms');
var fileStream:FileStream = new FileStream();
XML.ignoreProcessingInstructions = false; //newly added
fileStream.open(file, FileMode.READ);
var xml:XML = new XML(fileStream.readUTFBytes(fileStream.bytesAvailable));
fileStream.close();

There is a static property in the XML class called ignoreProcessingInstructions (which is true by default) that you could try setting before reading in your file. See this help page.
After some Google-ing, it appears that processing instructions outside of the root node may not be available, since the XML object starts with the root node. In that case, you may have to read the file in as standard text, save the processing line(s) before the root node, and then write them to the output file before you write the actual XML contents.

Related

How to write files to a specific directory?

I'm trying to let the user select a directory and then write files to that directory.
I have this code that lets a user browse for a directory:
var file:flash.filesystem.File = new flash.filesystem.File();
file.browseForDirectory("Select a directory");
file.addEventListener(Event.SELECT, selectHandler);
protected function selectHandler(event:Event):void {
// these contain the path where I want to save files to
Object(fileReference).url;
Object(fileReference).nativePath;
// how do I create a file in that directory?
}
How do I create a file in the directory that the user selects?
Your select handler code does not seem to be correct. You should get the reference of the Folder which is an object of the type File by doing event.currentTarget, and not Object or fileReference.
Next you can create a file using the FileStream class. Your selectHandler code should look like this:
protected function selectHandler(event:Event):void
{
var targetDirectory:File = event.currentTarget as File;
var file:File = targetDirectory.resolvePath("htmlFile.html");
var stream:FileStream = new FileStream();
stream.open(file, FileMode.WRITE);
stream.writeUTFBytes("Any Text you want to create");
stream.close();
}
Will work in AIR projects.
Hope this answers your question.

FileReference.save ensuring it has extension

I need to save an XML with some settings and wanted to save them as my own filetype (.genconf for example). When i use..
var f:FileReference = new FileReference();
f.save( MyByteArray);
..I can allow the user to browse to save, but it only uses an extension if they enter in manually (which they definitely wont).
Is there a way to check the filename they enter, and amend/append it before the file is written?
Here's how i did it in the end (with AIR):
//on save clicked
public function export(e:MouseEvent){
var file:File = File.desktopDirectory;
file.browseForSave("Save");
file.addEventListener(Event.SELECT, onSaveSelect);
}
public function onSaveSelect(e:Event){
//create XML stuff here
var config:XML = new XML(<config />)
// compressing before saving
var bytes:ByteArray = new ByteArray();
bytes.writeUTFBytes( config );
bytes.compress();
//get browse location
var saveFile:File = File(e.target);
var directory:String = saveFile.url;
//check if by miracle they put the extension in, then add it
if(directory.indexOf(".genconf ") == -1){
directory += ".genconf ";
}
//use the new path with the extension
var file:File = new File();
file = file.resolvePath(directory);
var fileStream:FileStream = new FileStream();
fileStream.addEventListener(Event.CLOSE, onClose);
fileStream.openAsync(file, FileMode.WRITE);
fileStream.writeBytes(bytes);
fileStream.close();
}
I think that for Flash security reason you can not force the file extension in any way, in addition the file name typed by user is a read-only information so you can not modify it.
So for your case, you want to save files with the .genconf extension, I think that you can :
Request the file name to your user, before showing the save dialog, and then add the extension to have the default file name for the save dialog.
OR
Fix the default file name with your extension using time-stamp, randomized name, ... and demand to your user to save the file directly without editing the name.
In all cases, you will get a code like this :
const extension:String = '.genconf';
var file_ref:FileReference = new FileReference()
file_ref.save('your_data', 'default_file_name' + extension);
Hope that can help.

Zip a folder in as3 Adobe AIR

I have created an Air app that after user interaction will creat a folder with bmp's, xml and text doc's.
All works apart from making the final zip which needs to be automatic.
I have been looking for a solution to this but cant find it.
Perhaps I am just not seeing it, and if so, can someone show me please.
My original posting on this is here ---
zip many files with Air as3 flash
The closest thing I have found was this one --- zip a folder using fzip
But for some reason my coment was deleted which was --
I like this. It is the closest I have come to a working solution to my own problem. That said, I tested this and it works nicely as is. Can this script be moded to run without interaction??? I am in need of it for a program that I have written. ANY asistance is welcom........ apart from just pointing me to Adobe referance as it dose not have anything like what I need. (well that I can see or find)
So now I am re-asking the comunity.
For some reason it will work with manual selection and manual save-to, but not aotonomusly.
There must be a workround to this even if it requires another full page of script.
====================================================================
UPDATE:
For closing this off, I have finally got my solution.
You can find it here. "zip file contents have no data".
Hope that my problem can help someone in the future.
Try using the as3 commons zip library.
http://www.as3commons.org/as3-commons-zip/index.html
In order to do this you're going to need to load your directory, loop through all its contents and load each asset.
This code snippet includes a bulk loader to handle that for you.
warning
I pulled most of this code out of a project where I was doing something similar but I have not tested it as is. There may be some syntax errors!
private var zip:Zip;
zip = new Zip();
zip.addEventListener(IOErrorEvent.IO_ERROR, this.createNewZip); //creates a new zip
zip.addEventListener(Event.COMPLETE, handleZipLoaded); //loads the current zip, this is not shown here
zip.load(new URLRequest(File.applicationStorageDirectory.resolvePath("myZip.zip").url)); //path to your zip file
Method to create your new zip file
private function createNewZip(e:IOErrorEvent):void{
trace("no zip");
var stream:FileStream = new FileStream();
stream.open(File.applicationStorageDirectory.resolvePath("myZip.zip"), FileMode.WRITE);
zip.serialize(stream);
stream.close();
}
You can use this to add all items in a directory to your zip file.
private function addDirToZip():void{
var f:File = File.resolvePath("Your Dir");
//this will be called when your directory listing has loaded
f.addEventListener(FileListEvent.DIRECTORY_LISTING, handleDirLoaded);
//you can also get the dir listing inline and not use a listener
//doing it async will prevent ui lock
f.getDirectoryListingAsync();
}
Next your going to need to load all of the files
protected function handleDirLoaded(e:FileListEvent):void{
loadExternal = new Vector.<File>; //vector used to keep a handle on all files
e.target.removeEventListener(FileListEvent.DIRECTORY_LISTING, handleDirLoaded);
for(var i:int = 0 ; i < files.length ; i++){
var f:File = files[i] as File;
if(f.extension == "File Types you want"){ //you can do some file type checking here
loadExternal.push(f);
}
}
//start loading in the files
loadFile();
}
This will go through the loadExternal vector and load all files
private function loadFile():void{
currentFile = loadExternal.shift(); //returns the first item off the array
//load the file
var l:Loader = new Loader();
l.contentLoaderInfo.addEventListener(Event.COMPLETE, handleLoaded);
l.load(new URLRequest(currentFile.url));
}
Once each item is loaded you can store it for addition into the zip
private function handleLoaded(e:Event):void{
var l:Loader = e.target.loader as Loader;
l.contentLoaderInfo.removeEventListener(Event.COMPLETE, handleLoaded);
//storing everything in a dictionary
assets[currentFile.name] = l.content;
//if we still have items to load go and do it all again
if(loadExternal.length != 0){
loadFile();
} else {
//now all files are loaded so lets add them to the zip
addAssetsToZip();
}
}
This is where all the loaded files actually get put into the zip and it is saved
private funcion addAssetsToZip():void{
for(var fileName:String in assets){
var ba:ByteArray = new ByteArray(); //going to write this to the zip
//make an object that holds the data and filename
var data:Object = {};
data.name = fileName;
data.content = assets[fileName];
ba.writeObject(data);
//write this file to the zip
zip.addFile(key, ba, false);
}
//and finally save everything out
zip.close();
var stream:FileStream = new FileStream();
stream.open(File.applicationStorageDirectory.resolvePath("myZip.zip"), FileMode.WRITE);
zip.serialize(stream);
stream.close();
}

upload a zip file using HTTP POST via actionscript 3.0

I have a zip file that is created using drag and drop on a view in my desktop Flex 4.6 app.
This triggers a service that will automatically upload the zip file.
I am able to use the following code to send metadata about the zip file to the server.
var urlRequest:URLRequest = new URLRequest(PUBLISH_ZIP_FILE_URL);
// set to method=POST
urlRequest.method = URLRequestMethod.POST;
var params:URLVariables = new URLVariables();
params['data[File][title]'] = 'Title1';
params['data[File][description]'] = 'desc';
// params['data[File][filename]'] = I am not sure exactly what to use here
// If this is a webpage, I expect to use input type="file" with the name as data[File][filename]
urlRequest.data = params;
addLoaderListeners();
// set it such that data format is in variables
loader.dataFormat = URLLoaderDataFormat.VARIABLES;
loader.load(urlRequest);
I have read https://stackoverflow.com/questions/8837619/using-http-post-to-upload-a-file-to-a-website
However, immediately they start off with ByteArray, which I am not sure how to convert my zip file at all.
Please advise.
Embarrassing but I found my answer 42 mins after I posted the question.
A little bit of a rubber duck problem solving going on here.
http://www.codinghorror.com/blog/2012/03/rubber-duck-problem-solving.html
Short answer: Use File class and specifically the method upload which is extended from the FileReference class.
Long answer:
var urlRequest:URLRequest = new URLRequest(PUBLISH_ZIP_FILE_URL);
// set to method=POST
urlRequest.method = URLRequestMethod.POST;
var params:URLVariables = new URLVariables();
params['data[File][title]'] = 'Title1';
params['data[File][description]'] = 'desc';
// this is where we include those non file params and data
urlRequest.data = params;
// now we upload the file
// this is how we set the form field expected for the file upload
file.upload(urlRequest, "data[File][filename]");

How to read .xlsx file contents in flex3

I need to know how to read .xlsx file contents in flex3. Does anyone comes across this problem please give some idea to accomplish this task. If any good API please let me know.
I tried to read .xlsx file using the below sample code but its not working, but its working fine for .xls file.
// on creation complete
private function onCreate(e:Event):void
{
var request:URLRequest = new URLRequest("C://test.xlsx");
var urlLoader:URLLoader = new URLLoader(request);
urlLoader.addEventListener(Event.COMPLETE, onURLLoaderComplete);
urlLoader.dataFormat = URLLoaderDataFormat.BINARY;
urlLoader.load(request);
}
// on file load complete
private function onURLLoaderComplete(event:Event):void
{
loadedFile = event.target.data;
var excelFile:ExcelFile = new ExcelFile();
excelFile.loadFromByteArray(loadedFile);
sheet = excelFile.sheets[0];
Alert.show(sheet.getCell(1,0).value)
DataGrid.dataProvider=sheet.values;
}
Thanks in Advance.
If you only need cell values, save it as CSV - it is very simple to parse (unlike xlsx.)