Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Flex's FileReference.save() can only be called in a user event handler -- how can I get around this?

I need to call FileReference.save() after a web service call has completed, but this method has a restriction: "In Flash Player, you can only call this method successfully in response to a user event (for example, in an event handler for a mouse click or keypress event). Otherwise, calling this method results in Flash Player throwing an Error exception." (from the documentation here)

This restriction is a bit vague. Does it mean that I can only call the FileReference.save() method from within an event handler function that is registered as a listener for certain types of user events? If so then exactly which user events are valid? (Perhaps there's an event that will never be dispatched by user interaction with my application and I could register an event handler function for that event type and make the save() call from within that function?)

My difficulty is that I can't safely call the FileReference.save() method until my web service returns with the data that will be used as the argument of the FileReference.save() method call, so the event that triggers the FileReference.save() call is actually a ResultEvent rather than a user event, and I'm leery of dispatching a new (faux) user event type in order to be able to trigger the FileReference.save() call unless it's definitely a user event that would never be dispatched as a result of actual user interaction with my application.

In a nutshell what I'm doing now is this: I have a function that is registered as a handler for a button click. In this function I make my web service call to fetch data from the server. I also have a result handler function which gets invoked when the web service call completes, and it's in here that I want to call the FileReference.save() method since it's at this point that I know that the data is ready to be saved to a file. But the aforementioned restriction is blocking me from doing this -- I get an error:

Error #2176: Certain actions, such as those that display a pop-up window, 
may only be invoked upon user interaction, for example by a mouse click 
or button press.

I've tried many things to get around this such as creating a second mouse click event handler function with the FileReference.save() call within and calling it after a timeout interval (to give the web service time to complete), but I keep running into the same error -- maybe that approach doesn't work since the second function isn't registered as an event listener for the event type used as its argument.

I'm new to Flex development so perhaps I'm just not thinking about this in the right way. If anyone can suggest another approach I'd really appreciate it. Thanks in advance for your comments or suggestions.

--James

like image 963
James Adams Avatar asked Jul 21 '10 17:07

James Adams


3 Answers

Adobe does this as a sort of security measure to ensure users are the ones messing with files rather than potentially harmful code. My understanding is that they enforce this by only allowing handlers of (click?) events that originate from UI components to execute the FileReference methods, so generating your own events programmatically will not work, although I have not tried to verify this. Unfortunately the best resolution I've found is to re-work the UI a bit to conform to this constraint. In your particular situation, you could make this a two click process with a button that says something like "Prepare Download", which changes to "Download File" after the web service is complete. This is less than ideal from a user perspective, but I don't think there's much else that can be done unless you can somehow complete your web service call prior to displaying the button that triggers the FileReference.save() call.

like image 103
Wade Mueller Avatar answered Nov 20 '22 21:11

Wade Mueller


After struggling for that for well, a couple hours I found a workaround: you can use both mouseDown AND mouseUp events instead of just click.

For instance: s:Button mouseDown="prepare_PDF()" mouseUp="save_PDF()"

Works fine for me!

Happy coding!

--Thomas

like image 35
Thomas Avatar answered Nov 20 '22 22:11

Thomas


As a workaround I used the ExternalInterface class. I created a javascript function with this code

function downloadFile (url) {
            window.open(url);
        }

An in AS3 I call

var url = 'www.example.com/downloadfile.php?file_id=xxx';
ExternalInterface.call('downloadAttachmentFile', url);

So with that I transfer the file handling to JS/HTML.

like image 2
havoc24k Avatar answered Nov 20 '22 22:11

havoc24k