2010-07-21 27 views
12

Po wywołaniu usługi WWW muszę wywołać FileReference.save(), ale ta metoda ma ograniczenie: "W programie Flash Player można wywoływać tę metodę tylko w odpowiedzi na zdarzenie użytkownika (na przykład w obsługa zdarzeń dla kliknięcia myszą lub zdarzenia typu keypress). W przeciwnym razie wywołanie tej metody spowoduje, że Flash Player rzuci wyjątek błędu. " (z dokumentacji here)Funkcja FileReference.save() Flexa może być wywołana tylko w procedurze obsługi zdarzeń użytkownika - jak mogę obejść ten problem?

To ograniczenie jest nieco niejasne. Czy to znaczy, że mogę wywołać tylko metodę FileReference.save() z funkcji obsługi zdarzeń, która jest zarejestrowana jako detektor dla określonych typów zdarzeń użytkownika? Jeśli tak, to jakie dokładnie zdarzenia użytkowników są prawidłowe? (Być może jest zdarzenie, które nigdy nie zostanie wysłane przez interakcję użytkownika z moją aplikacją i mógłbym zarejestrować funkcję obsługi zdarzeń dla tego typu zdarzenia i wykonać wywołanie save() z tej funkcji?)

Moja trudność polega na tym, że nie można bezpiecznie wywołać metody FileReference.save(), dopóki moja usługa sieciowa nie zwróci danych, które będą używane jako argument wywołania metody FileReference.save(), więc zdarzenie wywołujące wywołanie FileReference.save() jest w rzeczywistości wynik ResultEvent, a nie zdarzenie użytkownika, i nie jestem pewien, czy wysłać nowy (faux) typ zdarzenia użytkownika, aby wywołać wywołanie FileReference.save(), chyba że jest to definitywnie zdarzenie użytkownika, które nigdy nie zostanie wysłane jako wynik rzeczywistej interakcji użytkownika z moją aplikacją.

W skrócie, co robię teraz jest to: Mam funkcję zarejestrowaną jako program obsługi dla kliknięcia przycisku. W tej funkcji wykonuję moje zgłoszenie serwisowe do pobierania danych z serwera. Mam również funkcję obsługi wyników, która jest wywoływana po zakończeniu wywołania usługi sieci Web, i tutaj chcę wywołać metodę FileReference.save(), ponieważ w tym momencie wiem, że dane są gotowe do zapisania w plik. Jednak wspomniane ograniczenie blokuje mnie od robienia tego - pojawia się błąd:

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. 

próbowałam wielu rzeczy, aby obejść ten problem, takich jak tworzenie drugie kliknięcie myszy funkcję obsługi zdarzenia z FileReference.save () zadzwonić i wywołać go po upływie limitu czasu (aby czas usługi sieciowej się zakończył), ale ciągle mam ten sam błąd - może to nie działa, ponieważ druga funkcja nie jest zarejestrowana jako detektor zdarzeń dla typu zdarzenia używanego jako jego argument.

Jestem nowy w rozwoju Flex, więc może po prostu nie myślę o tym we właściwy sposób. Jeśli ktokolwiek może zaproponować inne podejście, naprawdę to doceniam. Z góry dziękuję za komentarze i sugestie.

--James

Odpowiedz

18

Adobe robi to jako swego rodzaju zabezpieczenie, aby zapewnić użytkownikom są te Messing z plikami zamiast potencjalnie szkodliwego kodu. Rozumiem, że wymuszają to, dopuszczając jedynie obsługę zdarzeń (kliknięć?), Które pochodzą z komponentów interfejsu użytkownika w celu wykonania metod FileReference, więc generowanie własnych zdarzeń programowo nie będzie działać, chociaż nie próbowałem tego sprawdzać. Niestety najlepsza rozdzielczość, jaką znalazłem, polega na ponownym opracowaniu interfejsu użytkownika w celu dostosowania się do tego ograniczenia. W tej konkretnej sytuacji możesz zrobić to za pomocą dwukrotnego kliknięcia za pomocą przycisku z napisem "Przygotuj pobieranie", który zmienia się na "Pobierz plik" po zakończeniu usługi internetowej. Jest to mniej niż idealne z punktu widzenia użytkownika, ale nie sądzę, aby można było zrobić jeszcze coś innego, chyba że uda się jakoś dokończyć wywołanie usługi sieciowej przed wyświetleniem przycisku uruchamiającego wywołanie FileReference.save().

+2

To jest dokładne. Aplikacje Flash oparte na przeglądarce powinny przestrzegać normalnych zasad środowiska sandbox przeglądarki. Inną opcją byłoby użycie środowiska Adobe AIR, które wychodzi poza obszar izolowany przeglądarki (ale wymaga użytkownika, aby zainstalować aplikację). –

4

Po tym, jak walczyłem o to za dobrze, kilka godzin znalazłem obejście: możesz użyć zarówno zdarzeń mousedown, jak i myszy, zamiast po prostu kliknąć.

Na przykład: s: Przycisk mouseDown = "prepare_PDF()" mouseUp = "save_PDF()"

działa dobrze dla mnie!

Szczęśliwe kodowanie!

--Thomas

+0

Dzięki za to, Thomas. Nie zmywałem tej aplikacji od jakiegoś czasu, więc może nie mam okazji przetestować tego, ale wygląda to na dobre rozwiązanie i warto o tym pamiętać. –

+4

Jeśli plik prepare_PDF jest asynchroniczny, wydaje się, że będziesz w stanie wyścigu z save_PDF. Co robisz w save_PDF, jeśli ready_PDF jeszcze się nie zakończyło? – paleozogt

0

To jest komentarz na odpowiedź Thomasa (nie mam wystarczająco dużo XP jeszcze komentarza): the mousedown i mouseup obejście działa ładnie. Wystarczy pamiętać, że jeśli wprowadzisz jakieś zmiany w prepare_PDF(), które wymagają "cofnięcia" w save_PDF(), to dobrym pomysłem jest wywołanie tego kodu również w zdarzeniu mouseout, ponieważ może istnieć przypadek, w którym użytkownik znajduje się na przycisku, ale następnie odsuwa mysz od przycisku.

Było to szczególnie istotne w moim przypadku, w którym zwiększamy rozmiar znaku wodnego na obrazie, gdy użytkownik kliknie przycisk pobierania (który uruchamia wywołanie .save()). Zmniejszam rozmiar znaku wodnego do poziomu normalnego w zdarzeniach mousedown i mouseout.

+0

Ponieważ wykonujesz wywołanie usługi internetowej, nie widzę, jak to działa. Wywołujesz wywołanie usługi web z mouseDown i zakładasz, że zostało ukończone przed upływem czasu. Co się stanie, jeśli pojawi się MouseUp * przed * zakończeniem połączenia z serwisem internetowym? – paleozogt

+0

@paleozogt wywołanie usługi internetowej jest wywoływane na mouseUp, a nie mouseDown. – Jaffer

+1

W przykładzie Thomasa, 'prepare_PDF' (wywoływanym z' mouseDown') jest wywołaniem usługi sieciowej, prawda? Następnie 'save_PDF' (wywoływane z' mouseUp') wywołuje FileReference.save. – paleozogt

2

Jako obejście zastosowałem klasę ExternalInterface. I stworzył funkcji javascript z tym kodem

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

in AS3 Wzywam

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

Więc z tym przenieść plik do obsługi JS/HTML.

+0

Proszę zwrócić uwagę na to, czy odpowiadasz na aktywny wątek ... ten wątek ma 2 lata i ma zaakceptowaną odpowiedź! – durron597

+8

Tak, ale wiele osób takich jak ja kończy się na "starych" wątkach z google. Dlaczego więc nie zaoferować alternatywy dla innego poszukującego odpowiedzi, takiego jak ja? – havoc24k

+0

Uzgodnione.Przyszedłem tutaj z wyszukiwarki Google i chcę otrzymywać aktualne odpowiedzi, nie tylko te, które podobały się OP! – Venryx

0

Miałem ten sam problem, wybrałem metodę flash.net. Zadzwoń pod numer flash.net.navigateToURL(url); z ActionScript lub navigateToURL(url); z mxml.

0

Co zrobić, aby rozwiązać ten problem, to pokazać komunikat z anonimową funkcją, więc nie muszę tworzyć przycisku.

Alert.show("Do you wish to download the file?", "Confirm", Alert.OK | Alert.CANCEL, this, function (eventObj:CloseEvent):void { 
                            if (eventObj.detail == Alert.OK) { 
                             fileReference.save(zipOut.byteArray, dateFormater_titulo.format(new Date()) + ".zip"); 
                            }//if 
                           }/*function*/, null, Alert.OK);