2010-01-03 11 views
6

nel mio progetto, consente agli utenti di scattare foto utilizzando la classe FileReference. Carico quindi queste immagini nelle loro proprietà .data, usando la funzione load(). Dopo questo, eseguo alcune manipolazioni locali e le invio al server.Flex: DeepCopy di FileReference

Quello che mi piacerebbe fare, è poter essere in grado di scorrere nuovamente le FileReferenze selezionate, caricarle in proprietà .data, eseguire manipolazioni diverse e inviarle nuovamente al server. So che dovrei essere in grado di farlo da un evento invocato dall'utente, che non è un problema qui.

Il problema è che, una volta caricato FileReference per la prima volta, non riesco a scaricarlo in alcun modo e non riesco a conservare i dati per tutte le immagini nella memoria perché sono enormi.

Quindi immagino ci sia solo una cosa che posso fare, che sta eseguendo un DeepCopy su FileReference ... Quindi ho potuto caricare la prima versione, eliminarla e usare la copia per la seconda 'esecuzione'.

Ho provato a utilizzare ObjectUtil.copy, ma quando accedo ad es. Proprietà .name della copia, non riesce con:

Error #2037: Functions called in incorrect sequence, or earlier call was unsuccessful. 

a nome flash.net::FileReference/get()

il frammento di rilevante:

registerClassAlias("FileReference",FileReference); 
masterFileList.addItem(FileReference(ObjectUtil.copy(fr_load.fileList[i]))); 
trace(masterFileList[i].name) 

v'è forse vero che sono alcune proprietà protette della classe FileReference che ne impediscono la copia? Se è così, posso aggirare questo in qualche modo? O c'è qualche altra soluzione al mio problema generale?

Apprezzo qualsiasi suggerimento/idea!

+0

L'ho portato su actionscript.org e ho elaborato un po 'di più, ma ancora nessuna speranza. Ad ogni modo ecco il thread: http://www.actionscript.org/forums/showthread.php3?t=227441 – supo

+0

Sto supponendo che questo non può essere fatto, dal momento che ci sono probabilmente alcuni handle nell'oggetto FileReference che non sono accessibili affatto usando ActionScript. Non sarei sorpreso se la classe FileReference non fosse nemmeno implementata in ActionScript. –

risposta

1

non è possibile utilizzare ObjectUtil.copy. Questo metodo è progettato per copiare solo oggetti dati (classi VO).

È necessario creare un nuovo FileReference e copiare le porzioni, una alla volta. Creare una funzione per fare questo ..

+0

Ciao, grazie per la risposta. Ma hai mai provato a copiare un oggetto FileReference come quello? Voglio dire, le proprietà cruciali sono probabilmente protette e quelle che sono pubbliche sembrano essere di sola lettura. Puoi accedere a .data solo dopo aver caricato() il FR, quindi puoi copiare i dati dopo questo. Ma questo non è quello che volevo. Ho bisogno di copiarlo prima di caricarlo. In questo modo posso caricarlo separatamente nella prima e nella seconda. – supo

1

Lo copia in un file temporaneo e quindi il caricamento del file temporaneo funziona? Per esempio

 var fileRef:FileReference = new FileReference(); 
     fileRef.browse(); 

     ...................... 

     var tmpFile:File = File.createTempFile(); 
     try { 
      var tmpFileStream:FileStream = new FileStream(); 
      tmpFileStream.open(tmpFile, FileMode.WRITE); 
      trace("Opened file: " + tmpFile.nativePath); 
      tmpFileStream.writeBytes(fileRef.data); 
      trace("copied file"); 
     } catch (error:Error) { 
      trace("Unable to open file " + tmpFile.nativePath + "\n"); 
      throw error; 
     } 
+0

Si consiglia di memorizzare tutte le immagini nella qualità completa nella memoria e quindi di caricarle dalla memoria? Questo non aiuterà, perché anche un numero limitato di immagini (come 10) che non sono nemmeno della migliore qualità (diciamo 3MB/ognuna) richiedono alcune centinaia di megabyte di RAM, anche se le codifico in JPEG e memorizzato loro dopo. E mi piacerebbe lavorare con 100 o più immagini. – supo

+0

Hmm aspetta un secondo, ora ho visto che stai creando un file lì. Non createTempFile associato ad AIR? Non l'ho menzionato, ma questa non è un'applicazione AIR. – supo

1

Sto pensando che l'operazione è completamente non consentita, per buoni motivi. Se è possibile duplicare un nuovo FileReference tramite il codice ActionScript, sarà anche possibile fabbricare un oggetto FileReference tramite il codice ActionScript. Certo, sarebbe un buco di sicurezza piuttosto brutto se si potesse forzare il caricamento di un file arbitrario.

Mantenere una copia dei dati nella memoria non è poi così male come soluzione. Dopotutto, è temporaneo. Il tipico computer client dovrebbe essere in grado di gestire alcune centinaia di MB di dati senza problemi. È certamente un'opzione migliore rispetto al fatto che il loro browser faccia due caricamenti separati, il che è ciò che la tua soluzione tentata finirebbe per fare.

Una soluzione potenziale completamente diversa a questo problema è evitare del tutto la manipolazione delle immagini da parte di Flex. Flex potrebbe pubblicare il file caricato direttamente sul server e il server potrebbe eseguire la stessa manipolazione dell'immagine. Naturalmente, se la manipolazione è guidata attraverso le interazioni dell'utente, allora non funzionerebbe affatto.

+0

Qualche centinaia di MB in più? AFAIK non è possibile memorizzare 1 immagine in meno di 50 MB di RAM. Queste immagini sono jpeg e pesano circa 1-5 MB quando vengono compresse su disco. Mi piacerebbe lavorare con almeno 100 immagini, il che rende 5 GB di RAM, il che non è accettabile in nessun modo. L'altra alternativa che suggerisci mi è venuta in mente. La manipolazione non è guidata dall'utente, MA questo approccio richiederebbe all'utente di aspettare fino a quando tutte le immagini vengono caricate in buona qualità e questo può richiedere circa un'ora. Non voglio costringere l'utente ad aspettare così a lungo all'inizio del suo lavoro con l'app .. – supo

+0

Se puoi suggerire un modo in cui memorizzare le immagini nella RAM in modo più efficiente, sarebbe bello. Finora ho provato delle bitmap di base che sono stupide e poi ho provato a codificarle su Jpeg e ad archiviarle come byte. – supo

+0

Non è necessario memorizzare tutte le centinaia di immagini contemporaneamente. Potresti elaborarli uno alla volta, rilasciando il buffer temporaneo dopo aver finito con ciascuno di essi. – Jacob

1

Stavo cercando di fare quasi esattamente quello che stavi facendo, e ho quasi rinunciato dopo aver letto alcune risposte, ma penso di aver trovato un modo per farlo.Ho scoperto che se si dispone di un oggetto FileReference, se si chiama load() più volte, funzionerà, ma il problema principale è che si conservano i byte ad alta risoluzione in memoria dopo il primo caricamento. Come hai detto, per le persone che non conoscono l'elaborazione delle immagini, questo è un grande no-no.

Il modo per aggirare questo è che dopo il primo load(), è necessario chiamare il metodo cancel() su FileReference. Dai miei test fino ad ora, sembra che cancellerà i byte in FileReference, e load() funzionerà ancora se lo chiami una seconda volta. L'ho provato solo sul mio sistema fino ad ora, ma funziona bene lì. Solo una parola di cautela, questo non è un comportamento esplicitamente definito nell'API, quindi è sicuramente soggetto a modifiche, ma potrebbe aiutarti a capire dove devi andare nel frattempo.

Spero che questo aiuti.