2010-07-21 18 views
12

Devo chiamare FileReference.save() dopo che una chiamata al servizio web è stata completata, ma questo metodo ha una restrizione: "In Flash Player, è possibile chiamare questo metodo solo in risposta a un evento utente (ad esempio, in un gestore di eventi per un clic del mouse o un evento keypress), altrimenti, chiamando questo metodo, Flash Player genera un'eccezione di errore. " (dalla documentazione here)Flex's FileReference.save() può essere chiamato solo in un gestore di eventi utente - come posso aggirare questo?

Questa restrizione è un po 'vaga. Significa che posso solo chiamare il metodo FileReference.save() all'interno di una funzione di gestore eventi registrata come listener per determinati tipi di eventi utente? Se è così allora esattamente quali eventi utente sono validi? (Forse c'è un evento che non verrà mai inviato dall'interazione dell'utente con la mia applicazione e potrei registrare una funzione di gestore di eventi per quel tipo di evento e effettuare la chiamata save() da quella funzione?)

La mia difficoltà è che io impossibile chiamare il metodo FileReference.save() fino a quando il mio servizio web non ritorna con i dati che verranno utilizzati come argomento della chiamata al metodo FileReference.save(), quindi l'evento che attiva la chiamata FileReference.save() è in realtà un evento ResultEvent piuttosto che un evento utente e sono lieto di inviare un nuovo tipo di evento utente (falso) per poter attivare la chiamata FileReference.save() a meno che non si tratti di un evento utente che non verrà mai inviato come un risultato dell'interazione dell'utente con la mia applicazione.

In poche parole quello che sto facendo ora è questo: ho una funzione che è registrata come gestore per un clic del pulsante. In questa funzione faccio la mia chiamata al servizio web per recuperare i dati dal server. Ho anche una funzione di gestione dei risultati che viene richiamata al termine della chiamata al servizio web, ed è qui che voglio chiamare il metodo FileReference.save() poiché è a questo punto che so che i dati sono pronti per essere salvati in un file. Ma la limitazione di cui sopra mi sta bloccando dal fare questo - ottengo un errore:

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. 

Ho provato molte cose per ottenere intorno a questo come ad esempio la creazione di una seconda funzione gestore di eventi click del mouse con il FileReference.save () chiama e chiama dopo un intervallo di timeout (per dare il tempo di completamento del servizio web), ma continuo a correre nello stesso errore - forse quell'approccio non funziona poiché la seconda funzione non è registrata come listener di eventi per il tipo di evento utilizzato come argomento.

Sono nuovo nello sviluppo di Flex, quindi forse non sto pensando a questo nel modo giusto. Se qualcuno può suggerire un altro approccio, lo apprezzerei molto. Grazie in anticipo per i vostri commenti o suggerimenti.

--James

risposta

18

Adobe fa questo come una sorta di misura di sicurezza per garantire che gli utenti sono quelli che pasticciano con i file, piuttosto che codice potenzialmente dannoso. La mia comprensione è che fanno rispettare ciò consentendo solo ai gestori di eventi (clic?) Che provengono da componenti dell'interfaccia utente di eseguire i metodi FileReference, quindi la generazione di eventi personali non funzionerà, anche se non ho provato a verificarlo. Sfortunatamente la migliore risoluzione che ho trovato è di rielaborare l'interfaccia utente un po 'per conformarsi a questo vincolo. Nella tua situazione particolare, potresti rendere questo processo a due clic con un pulsante che dice qualcosa come "Prepara download", che cambia in "Download file" una volta completato il servizio web. Questo non è l'ideale dal punto di vista dell'utente, ma non penso che ci sia molto altro che può essere fatto a meno che tu non possa in qualche modo completare la tua chiamata al servizio web prima di visualizzare il pulsante che attiva la chiamata FileReference.save().

+2

Questo è corretto. Ci si aspetta che le applicazioni Flash basate sul browser obbediscano alle normali regole sandbox del browser. Un'altra opzione potrebbe essere l'utilizzo di Adobe AIR che esce dalla sandbox del browser (ma richiede all'utente di installare l'app). –

4

Dopo aver lottato per quello per bene, un paio d'ore ho trovato una soluzione: è possibile utilizzare sia mouseDown AND eventi mouseUp anziché solo clic.

Per esempio: s: button mouseDown = "prepare_PDF()" mouseUp = "save_PDF()"

funziona bene per me!

Felice codifica!

--Thomas

+0

Grazie per questo, Thomas. Non ho incasinato questa applicazione tra qualche tempo, quindi potrei non avere la possibilità di testarlo, ma sembra una buona soluzione ed è qualcosa di buono da sapere e da tenere a mente. –

+4

Se prepare_PDF è asincrono, sembra che ti troverai in una condizione di competizione con save_PDF. Cosa fai in save_PDF se prepare_PDF non è ancora stato completato? – paleozogt

0

Questo è un commento sulla risposta di Thomas' (non ho abbastanza XP per commentare ancora): La soluzione mousedown e mouseup funziona bene. Solo una nota che se si apportano modifiche in save_PDF() a save_PDF(), è consigliabile chiamare tale codice anche nell'evento mouseout, poiché potrebbe esserci un caso in cui l'utente si trova sul pulsante, ma quindi sposta il mouse lontano dal pulsante.

Questo è stato particolarmente rilevante per il mio caso, in cui si aumenta la dimensione di una filigrana su un'immagine quando l'utente fa clic sul pulsante di download (che attiva la chiamata .save()). Riduco la dimensione della filigrana alla normalità negli eventi mousedown e mouseout.

+0

Dato che stai facendo una chiamata al servizio web, non vedo come funziona. Spegni la chiamata al servizio web da mouseDown e presumi che sia stata completata dal momento in cui si verifica il passaggio del mouse. Cosa succede se mouseUp si verifica * prima * la chiamata al servizio web è completa? – paleozogt

+0

@paleozogt la chiamata al servizio web viene attivata su mouseUp, non su mouseDown. – Jaffer

+1

Nell'esempio di Thomas, 'prepare_PDF' (chiamato da' mouseDown') è la chiamata al servizio web, giusto? Quindi 'save_PDF' (chiamato da' mouseUp') chiama FileReference.save. – paleozogt

2

Come soluzione alternativa ho utilizzato la classe ExternalInterface. Ho creato una funzione JavaScript con questo codice

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

An in AS3 che io chiamo

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

Quindi, con che trasferisco la gestione di JS/HTML file.

+0

Si prega di prestare attenzione a se si sta rispondendo ad un thread attivo ... questa discussione ha 2 anni e ha una risposta accettata! – durron597

+8

Sì, ma molte persone come me finiscono su "vecchi" thread di google. Quindi, perché non offrire un'alternativa ad un altro cercatore di risposte come me? – havoc24k

+0

concordato.Sono venuto qui da una ricerca su Google e voglio risposte aggiornate, non solo quella che piaceva all'OP! – Venryx

0

Ho avuto lo stesso problema, ho scelto di utilizzare i metodi di flash.net. Chiama flash.net.navigateToURL(url); da un actionscript o navigateToURL(url); da mxml.

0

Quello che faccio per risolvere questo è mostrare un messaggio di avviso con una funzione anonima quindi non devo creare un pulsante.

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); 
Problemi correlati