7 Replies Latest reply on Jun 3, 2011 2:38 AM by ministe

    Downloading Images - FileReference download error 2176

    ministe

      Hi everyone.

      I'm trying to download some images but getting this 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."

       

      The trouble is, it IS running off a button click - just indirectly.

       

      I'm trying to design a good architecture for my program, so have the Application, a dataStore and some value objects, for example, a pricebook containing and array of products, each called PricebookVO and ProductVO.

       

      What I'm doing when the application loads is doing a database query with another API that gives me a pricebook and all of its products, and i populate the value objects.  Relationship is obviously  PricebookVO -< ProductVO.  I wanted to download the images for the products at the same time but it won't let me due to the error above, so what I have now is a button bar and when the user clicks a button an event is bubbled up to the Application which changes the page, but what also happens is it checks to see if the user has clicked the Products button and if it has, it tells the PricebookVO to tell each of its ProductVO's to download their image (from a URL that was saved from the query.

       

      Presumably the error im getting now is because the download is not directly summoned by a user event but by an indirect event (ie user pushes button, code calls code which tries to download the file).  How can I download the images and still maintain my architecture?

       

      Also, am I getting confused?  I want to get a file from a server and save them in an mx.controls.Image on the ProductVO record, do I use the FileReference.Download method or something else?  Because on further inspection it looks as though the download method is for downloading something to the local machine with a download dialog box?

       

      Thanks

      Steven

        • 1. Re: Downloading Images - FileReference download error 2176
          Peter Blazejewicz Level 4

          Hi Steven,

           

          it has to run directly - that is it needs to be started within blocks of code run as direct results of user interaction. Consider:

          #1

          protected function clickHandler(event:MouseEvent):void

          {

             downloadFile();

          };

          protected function downloadFile():void

          {

               var fr:FileReference = new FileReference();

               try{

                    fr.download(request, "data.xml");

               } catch(error:Error)

               {

                    debug(error.message);

               }

          };

          and:

          #2

          protected function clickHandler(event:MouseEvent):void

          {

             setTimeout(downloadFile, 1);

          };

           

          protected function downloadFile():void

          {

               var fr:FileReference = new FileReference();

               try{

                    fr.download(request, "data.xml");

               } catch(error:Error)

               {

                    debug(error.message);

               }

          };

           

           

          #1 will succeed and won't throw runtime error 2176 - while #2 will throw 2176 runtime error as download is not directly started within block of code resulting from user action.

           

          regards,

          Peter

          • 2. Re: Downloading Images - FileReference download error 2176
            ministe Level 1

            I think I might be barking up the wrong tree with this, I'm assuming the download method is used to allow a user to download things to their computer, what I want to do is get an image from a specific url and store it as an image variable in my application to display on screen.  Apologies for what is probably a simple issue, but what is the best way to do that?  I think usually you'd use a service of some kind but since these images are stored at specific urls I dont think that's what I should do, am I right?

            • 3. Re: Downloading Images - FileReference download error 2176
              ministe Level 1

              Never mind I think I've sorted it, I'm using URLRequest and a Loader object and loading the image from it's url and onComplete im saving it to the Image like so:

              this.image.source = event.currentTarget.content;

               

              Is this OK, is there a better way?  I'm always happy for advice to improve the efficiency of the program.  I'm thinking storing the images locally might be more efficient in the long run anyway...

               

               

              private const IMG_URL     : String = "this is a url"
              private var request: URLRequest;
              private var loader : Loader;
              {
              this.request     = new URLRequest(IMG_URL+this.ImageID);
              this.loader     = new Loader()
              this.loader.contentLoaderInfo.addEventListener(Event.COMPLETE,onComplete);
              this.loader.load(request);
              }
              
              private function onComplete(event:Event):void{
                 this.image.source = event.currentTarget.content;
                 this.loader.contentLoaderInfo.removeEventListener(Event.COMPLETE,onComplete);
              }
              
              • 4. Re: Downloading Images - FileReference download error 2176
                Peter Blazejewicz Level 4

                Hello,

                 

                #1

                as mentioned in Flash runtime one cannot implement "local cache" via filesystem without user interaction. The problem is also that one is not allowed to get location of file created by user via FileReference.save(...) - so file once created is "lost" to application on next run. That is nearly not possible to build local cache with Flash runtime available api itself - *it is done* already via system for Flash runtime as most resources are already cached (most frequently directly via browser implementation - then via system networking features). So if you're requesting images via net - they are already stored in cache (*usually*).

                 

                #2

                You could store loaded image in application local storage via SharedObject - by converting bitmap to Base64 encoded string (or even loading bitmaps converted into that mode already and then converting in player to attach to display list), see e.g. on that forum:

                http://forums.adobe.com/message/3685301#3685301

                The caveats is that SharedObject (local storage) has limits imposed by default to its size - and can be completely disallowed by user (but that is separate topic).

                 

                #3

                I think you do not have to complicate things by adding additional layer to  your existing routine: when you got runtime computed URL into your hand ("IMG_URL+this.ImageID") - just use it as source for Image.source - property - which could be URL string. It will do all the magic of loading remote image on itself (and as explained in #1 it should use system caching for binary content I think).

                 

                regards,

                Peter

                • 5. Re: Downloading Images - FileReference download error 2176
                  ministe Level 1

                  Thanks for all your help Peter, its much appreciated.  I hate that useless feeling when learning a new language!

                   

                  So anyway, I was initially using image.source but thought to myself that's probably referencing the image from its server source which might be quite a hog, so wanted to store it myself, but if you say image.source does indeed handle the image itself and not just reference it from the source, thats good.

                   

                  My only remaining query is regarding how it is displaying.  I have a tileList which is rendering the images and it does work, however the images are loading on screen as I watch them, and if I scroll I then have to wait again whilst the images load.  If I then scroll back to the previuos part of the screen, where the images had previously already loaded, they have disappeared again and I once again have to wait for them to load.

                   

                  I know normally you'd embed them, but dont see how thats possible with the way I'm having to load them from the server?

                   

                  I have a method in my datastore like this:

                   

                   

                  public function getProds():ArrayCollection{
                   var imgs : ArrayCollection = new ArrayCollection();
                   for each (var pb : PricebookVO in pricebooks){
                    pb.getProdCount();
                    for each (var p2 : ProductVO in pb.products){
                     imgs.addItem(p2);
                    }
                   }
                   return imgs;
                  }
                  

                   

                  and in my products page:

                  <mx:TileList>
                    <mx:width>100%</mx:width>
                    <mx:height>100%</mx:height>
                    <mx:itemRenderer>components.Thumbnail</mx:itemRenderer>
                    <mx:dataProvider>{DataStore.getInstance().getProds()}</mx:dataProvider>
                  </mx:TileList>
                  

                   

                  components.Thumbmail is

                  <mx:Image>
                    <mx:width>100</mx:width>
                    <mx:height>75</mx:height>
                    <mx:source>{this.data.image.source}</mx:source>
                    <mx:toolTip>{this.data.prodCode}</mx:toolTip>
                  </mx:Image>
                  

                   

                  So, how can I stop the tilelist from having to constantly reload the images?  I get the impression that the solution might end up using a lot of memory to store the images somehow, so advice on the best way to do this is appreciated.

                   

                  Thanks!

                  • 6. Re: Downloading Images - FileReference download error 2176
                    Peter Blazejewicz Level 4

                    Hello,

                     

                    My advice is as follows:

                    #1

                    fine tune your application as it works now and don't over-estimate image flicking impact

                    #2

                    as of mx-only Flex SDK that is known issue: images are always re-loaded into containers/groups/lists - and it is always asynchronous - so even if loaded from browser/system cache - image will disappear just for fraction of time - and will blink on screen. That was known limitation and there are already existing fixes for that. For example one of earliest and well known:

                    http://web.archive.org/web/20090130132514/http://www.quietlyscheming.com/blog/2007/01/23/s ome-thoughts-on-doubt-on-flex-as-the-best-option-orhow-i-made-my-flex-images-stop-dancing/

                    (way back machine download links/demo links work OK)

                     

                    #3

                    if you switch to mixed mx/sparks or sparks only - you would benefit from platform caching solution for images in content groups. Here is a good introductory page:

                    http://help.adobe.com/en_US/flex/using/WSc5cd04c102ae3e97-33ad5caa12c719dc7c8-8000.html#WS c5cd04c102ae3e97-33ad5caa12c719dc7c8-7ffc

                     

                    hth,

                    kind regards,

                    Peter

                    • 7. Re: Downloading Images - FileReference download error 2176
                      ministe Level 1

                      Thanks for the reply again.

                      The link to the quietlyscheming site is dead, site appears to be dead.  But what I've discovered is instead of storing the images in an Image object, by storing it in a ByteArray the images load much faster so the blinking isnt as bad.

                       

                      Thanks for all your help!