Flex 3 multiple upload progress monitoring - apache-flex

I have a Flex3 application which has to be capable of uploading multiple files and monitoring each files individual progress using a label NOT a progress bar.
My problem is that a generic progress handler for the uploads has no way (that I know of) of indicating WHICH upload it is that is progressing. I know that a file name is available to check but in the case of this app the file name might be the same for multiple uploads.
My question: With a generic progress handler how does one differentiate between 2 multiple uploads with the same file name?
EDIT: answerers may assume that I am a total newb to Flex... because I am.

I use this:
private function _addFileListeners(dispatcher:IEventDispatcher):void {
dispatcher.addEventListener(Event.OPEN, this._handleFileOpen);
dispatcher.addEventListener(Event.SELECT, this._handleFileOpen);
dispatcher.addEventListener(Event.CANCEL, this._handleFileCancel);
dispatcher.addEventListener(ProgressEvent.PROGRESS, this._handleFileProgress);
dispatcher.addEventListener(DataEvent.UPLOAD_COMPLETE_DATA,this._handleFileComplete);
dispatcher.addEventListener(IOErrorEvent.IO_ERROR, this._handleError);
dispatcher.addEventListener(SecurityErrorEvent.SECURITY_ERROR, this._handleError);
}
where "dispatcher" is the file:
for (var i:uint = 0; i < fileList.length; i++) {
file = FileReference(fileList[i]);
this._addFileListeners(file);
this._pendingFiles.push(file);
}
and a sample handler:
private function _handleFileOpen(e:Event):void {
var file:FileReference = FileReference(e.target);
...
}
I'm not sure how you want to differentiate between two files with the same name. In my case, I send the files in a queue. So there's only ever 1 file being uploaded at a time. (pendingFiles).

If you are listening for ProgressEvents, these events have a currentTarget attribute that would have a reference to the object that has registered the event listener.
I'm assuming you know which file-uploading object goes with each object in the first place.
EDIT: Example using FileReference:
import flash.net.FileReference;
import flash.events.ProgressEvent;
import flash.utils.Dictionary;
public var files:Dictionary = new Dictionary(); // This will hold all the FileReference objects
public function loadFile(id:String):void
{
var file:FileReference = new FileReference();
// Listen for the progress event on this FileReference... will call the same function for every progress event
file.addEventListener(ProgressEvent.PROGRESS, onProgress);
// TODO: listen for errors and actually upload a file, etc.
// Add file to the dictionary (as key), with value set to an object containing the id
files[file] = { 'id': id };
}
public function onProgress(event:ProgressEvent):void
{
// Determine which FileReference dispatched thi progress event:
var file:FileReference = FileReference(event.target);
// Get the ID of the FileReference which dispatched this function:
var id:String = files[file].id;
// Determine the current progress for this file (in percent):
var progress:Number = event.bytesLoaded / event.bytesTotal;
trace('File "' + id + '" is ' + progress + '% done uploading');
}
// Load some files:
loadFile('the first file');
loadFile('the second file');

I ended up creating my own class that manages events for each uploading file

Related

Flutter redux How to perform polling

Redux seems to be a very nice architecture for mobile app development. However, mobile apps have some features that are not common for web apps.
In my case, I would like to start long polling /monitoring location/tracking file system (any action that watches some external state) after the start of some particular screen and stop when the screen is closed.
Let's say we have a function, that can emit multiple events over time.
Stream<Event>monitor();
I would like to listen to the function only when some particular screen is active.
What is the best way of doing that?
Suppose you have 3 pages: 'PageHome.dart', 'Page1.dart', 'Page2.dart'.
Create another dart file 'GlobalVariables.dart', create a class gv inside this file, create static redux 'stores' for the three pages.
create static var strCurPage in gv.
suppose each page has a variable that is to be changed by an external event, declare them in gv as static var also.
Codes in GlobalVariables.dart:
import 'package:redux/redux.dart';
enum Actions {
Increment
}
// The reducer, which takes the previous count and increments it in response to an Increment action.
int reducerRedux(int intSomeInteger, dynamic action) {
if (action == Actions.Increment) {
return intSomeInteger + 1;
}
return intSomeInteger;
}
class gv {
static Store<int> storePageHome =
new Store<int>(reducerRedux, initialState: 0);
static Store<int> storePage1 =
new Store<int>(reducerRedux, initialState: 0);
static Store<int> storePage2 =
new Store<int>(reducerRedux, initialState: 0);
static String strCurPage = 'PageHome';
static String strPageHomeVar = 'PageHomeInitialContent';
static String strPage1Var = 'Page1InitialContent';
static String strPage2Var = 'Page2InitialContent';
}
Import 'GlobalVariables.dart' in all other dart files.
Before navigate to a new page, e.g. from PageHome to Page1, set:
gv.strCurPage = 'Page1';
Inside your monitor function, if an external event happens, say, change the values of the variables in Page1 and Page2 (But user currently navigating in Page1):
void thisFunctionCalledByExternalEvent(strPage1NewContent, strPage2NewContent) {
gv.strPage1Var = strPage1NewContent;
gv.strPage2Var = strPage2NewContent;
if (gv.strCurPage == 'Page1') {
// Dispatch storePage1 to refresh Page 1
storePage1.dispatch(Actions.Increment);
} else if (gv.strCurPage == 'Page2') {
// Dispatch storePage2 to refresh Page 2
storePage2.dispatch(Actions.Increment);
} else {
// Do not need to refresh page if user currently navigating other pages.
// so do nothing here
}
}
I don't know whether this is the best way, but using redux and GlobalVariables.dart, I can:
know which page the user is currently navigating.
change the content of a page even when the user is not at that page when the event fires. (But the content will be shown when the user navigate to that page later)
force the user to go to a specific page no matter which page the user is navigating, when the event fires.

applying autosave features with javafx

I am creating an application for project management which has various features including saving and opening the saved file. My application is running smoothly but i want to add another feature in the application which will allow it to save the data after some time.
Here is my code for the save and save as functions.
#FXML
private void handleSave() {
File userstoryFile = mainApp.getUserStoryFilePath();
if (userstoryFile != null) {
mainApp.saveUserStoryDataToFile(userstoryFile);
} else {
handleSaveAs();
}
}
/**
* Opens a FileChooser to let the user select a file to save to.
*/
#FXML
private void handleSaveAs() {
FileChooser fileChooser = new FileChooser();
// Set extension filter
FileChooser.ExtensionFilter extFilter = new FileChooser.ExtensionFilter(
"XML files (*.xml)", "*.xml");
fileChooser.getExtensionFilters().add(extFilter);
// Show save file dialog
File file = fileChooser.showSaveDialog(mainApp.getPrimaryStage());
if (file != null) {
// Make sure it has the correct extension
if (!file.getPath().endsWith(".xml")) {
file = new File(file.getPath() + ".xml");
}
mainApp.saveUserStoryDataToFile(file);
}
}
Is it possible to add autosave feature here ( using timer function )? if yes, How?
click here to get complete application code
Something like this should be easy to implement using ScheduledExecutorService:
ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor();
executorService.scheduleWithFixedDelay(() -> mainApp.saveUserStoryDataToFile(file), 0, 1, TimeUnit.MINUTES);
For saving the data with a delay of one minute between saves (no initial delay).
Note that using this approach you need to take care of a few things:
Synchronize access to the data.
Prevent concurrent access to the file.
Making sure shutdown is called when (or before) the JavaFX platform exits.

flex FileReference load complete event never fired

I have an image which will be uploaded twice by flash. Besides, I'll do some resizing & compression stuff. So I have to load the data and create a BitmapData object.
_fileRef.addEventListener(Event.Complete, onLoadComplete);
_fileRef.load();
The problem is the complete event is never fired which could be checked from log message in console. What are the possibilities that such an event failed to be triggered?
my real code is shown as below:
private function prepareImage():void
{
_compressionFactor = 82;
if(as3_jpeg_wrapper==null)
{
as3_jpeg_wrapper = clibinit.init();
}
_fileRef.addEventListener(Event.COMPLETE, onImageComplete);
_fileRef.load();
}
private var tempLoader:Loader;
private var tempData:ByteArray;
private function onImageComplete(event:Event):void
{
Utils.log("loading data completed");
tempData = event.currentTarget.data;
_fileRef.removeEventListener(Event.COMPLETE,onImageComplete);
tempLoader = new Loader;
tempLoader.contentLoaderInfo.addEventListener(Event.COMPLETE,onImageLoaded);
tempLoader.loadBytes(tempData);
}
The fact is that the log message "loading data completed" is never printed. I've traced the whole process, flash stucked here. The function prepareImage is called via:
Utils.log("We'll resize & compress the picture to be uploaded");
prepareImage();

Flex mobile : how to know it is the very first time running the application

I googled but didn't find a post for Flex mobile..
All I want for now is display an user agreement popup from TabbedViewNavigatorApplication when the user uses the app for the first time
var agreementView: UserAgreement = new UserAgreement();
PopUpManager.addPopUp(agreementView, this,true);
PopUpManager.centerPopUp(agreementView);
but maybe more later.
Please help..
What i did in my desktop air app;
I guess this will work at a mobile app also.
Make sure you have write access;
open yourproject-app.mxml scroll down to the end of the document. In the section, uncomment the following permission:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
Now you can create files like for example an sqlite database.
At the applicationcomplete call the function checkFirstRun:
// functions to check if the application is run for the first time (also after updates)
// so important structural changes can be made here.
public var file:File;
public var currentVersion:Number;
private function checkFirstRun():void
{
//get the current application version.
currentVersion=getApplicationVersion();
//get versionfile
file = File.applicationStorageDirectory;
file= file.resolvePath("Preferences/version.txt");
if(file.exists)
{
checkVersion();
}
else
{
firstRun(); // create the version file.
}
}
public function getApplicationVersion():Number
{
var appXML:XML = NativeApplication.nativeApplication.applicationDescriptor;
var ns:Namespace = appXML.namespace();
var versionnumber:Number =Number(appXML.ns::versionNumber);
return versionnumber;
}
private function checkVersion():void
{
var stream:FileStream= new FileStream();
stream.open(file,FileMode.READ);
var prevVersion:String = stream.readUTFBytes(stream.bytesAvailable);
stream.close();
if(Number(prevVersion)<currentVersion)
{
// if the versionnumber inside the file is older than the current version we go and run important code.
// like alternating the structure of tables inside the sqlite database file.
runImportantCode();
//after running the important code, we set the version to the currentversion.
saveFile(currentVersion);
}
}
private function firstRun():void
{
// at the first time, we set the file version to 0, so the important code will be executed.
var firstVersion:Number=0;
saveFile(firstVersion);
// we also run the checkversion so important code is run right after installing an update
//(and the version file doesn't exist before the update).
checkFirstRun();
}
private function saveFile(currentVersion:Number):void
{
var stream:FileStream=new FileStream();
stream.open(file,FileMode.WRITE);
stream.writeUTFBytes(String(currentVersion));
stream.close();
}
private function runImportantCode():void
{
// here goes important code.
// make sure you check if the important change previously has been made or not, because this code is run after each update.
}
Hope this helps.
Greets, J.
Some you need to store whether the user has agreed to the agreement or not. IF they haven't agreed, then show it.
One way to do this would be to store a value in a shared object. Another way to do this would be to use a remote service and store such data in a central repository. I assume you'll want the second; so you can do some form of tracking against the number of users using your app.

child of child movie clip are null in imported object from flex to flash right after being created

I have an Movie Clip in Flash that have subobject of button type which has subobject of input text and movie clips. Right after creation core Moveclip all subobject are set to null, when I expect them to be valid objects.
// hierarchy:
// core:MC_Core_design
// button_1:B_Mybutton
// text_name // dynamic text with instance name
// mc_icon // movie clip with instance name
var core:MC_Core_design = new MC_Core_design();
addChild(core);
core.button_1.text_name.text = "hello world"; // error: text_name is null
core.button_1.mc_icon.visible = false; // error: mc_icon is null
MC_Core_design was created in Flash and exported to Actionscript. I've done this for button_1 class aswell. The code was written using Flex.
When I comment out both lines that result in error I get correct view of the core Movie clip with all subobject.
How can I set subobject properties right after object creation?
You need to listen for the Event.INIT from the class when it is created. (If you are not embedding a symbol using the Embed metatag then Flash takes a few milliseconds to initialize the loaded movieclip). This does not seem to be a problem if the Flash IDE swf/swc does not contain any actionscript)
The issue is sometimes it can be really quick, so it fires the INIT event before you get a chance to attach the event listener to the object. so you can't just attach it after you instantiate the object.
A work around is to embed the swf as a byte array, then use the loader class to load the embedded bytes (This lets you set the event listener before calling load).
e.g.
[Embed(source="assets.swf", mimeType="application/octet-stream")]
private var assetBytes:Class;
private var clip:MovieClip;
private var loader:Loader;
public function LoadBytesExample()
{
loader = new Loader();
loader.contentLoaderInfo.addEventListener(Event.INIT, onAssetLoaded);
loader.loadBytes(new assetBytes());
}
private function onAssetLoaded(e:Event):void
{
var loader:Loader = (e.currentTarget as LoaderInfo).loader;
(e.currentTarget as LoaderInfo).removeEventListener(Event.INIT, onAssetLoaded);
clip = loader.content as MovieClip;
this.addChild(clip);
clip.someTextField.text = "HELLO WORLD";
}
Sorry for the formatting, just wrote that off the top of my head
And the syntax for embedding the symbol (You won't need to load this via a loader as the actionscript in the external swf/swc is stripped).
[Embed(source="assets.swf", symbol="somesymbol")]
private var assetSymbol:Class;
private var clip:MovieClip;
public function LoadSymbolExample()
{
clip = new assetSymbol();
clip.sometext.text = "Hello World";
}
If I see it right, button_1:B_Mybutton is not yet initialized.
I mean something like : button_1:B_Mybutton = new B_Mybutton();
About the other two variables text_name & mc_icon as you describe if they have been initialized already (as you term them as instance names), Iguess they should not give you any problem.
Also I asssume that you are setting access modifiers to all as public.
If you still have problem... pls share how all the required variables are defined. Just the relevant part would be enough.

Resources