2010-01-03 15 views
6

en mi proyecto, dejo que los usuarios elijan imágenes utilizando la clase FileReference. Luego cargo estas imágenes en sus propiedades .data, usando la función load(). Después de esto, realizo algunas manipulaciones locales y las envío al servidor.Flex: DeepCopy de FileReference

Lo que me gustaría hacer es poder iterar nuevamente sobre las FileReferences elegidas, cargarlas en propiedades .data, realizar una manipulación diferente y enviarlas al servidor una vez más. Sé que debería poder hacer esto desde el evento invocado por el usuario, eso no es un problema aquí.

El problema es que una vez que se carga la FileReference por primera vez, no puedo descargarla de ninguna manera y no puedo guardar los datos de todas las imágenes en la memoria porque son enormes.

Así que supongo que hay una sola cosa que puedo hacer, que es realizar un DeepCopy en FileReference ... Luego podría cargar la primera versión, descartarla y usar la copia para la segunda 'ejecución'.

Intenté utilizar ObjectUtil.copy, pero cuando accedo, p. .name propiedad de la copia, falla con:

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

en nombre flash.net::FileReference/get()

el fragmento relevante:

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

no es cierto que Cuáles son algunas propiedades protegidas de la clase FileReference que impiden que se copie? Si es así, ¿puedo eludir esto de alguna manera? ¿O hay alguna otra solución para mi problema general?

¡Agradezco cualquier pista/idea!

+0

Lo mencioné en actionscript.org y elaboré un poco más, pero todavía no hay esperanza. De todos modos aquí está el hilo: http://www.actionscript.org/forums/showthread.php3?t=227441 – supo

+0

Supongo que esto no se puede hacer, ya que es probable que haya algunos identificadores en el objeto FileReference que no son accesibles en absoluto usando ActionScript. No me sorprendería si la clase FileReference ni siquiera se implementara en ActionScript. –

Respuesta

1

no puede usar un ObjectUtil.copy. Este método está diseñado para copiar solo objetos de datos (clases de VO).

debe crear una nueva FileReference y copiar las propiedades, una por una. Cree una función para hacer esto ...

+0

Hola, gracias por la respuesta. ¿Pero alguna vez ha intentado copiar un objeto FileReference así? Quiero decir, las propiedades cruciales probablemente están protegidas y las que son públicas parecen ser de solo lectura. Puede acceder a .data solo después de cargar() el FR, para que pueda copiar los datos después de esto. Pero esto no es lo que yo quería. Necesito copiarlo antes de cargarlo. De esta forma puedo cargarlo en la primera ejecución y en la segunda ejecución por separado. – supo

1

¿Lo copiaría en un archivo temporal y luego se cargaría el archivo temporal? Por ejemplo

 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

¿Sugiere que guarde todas las imágenes en la calidad completa en la memoria y las cargue desde la memoria? Eso no va a ayudar, porque incluso un pequeño número de imágenes (como 10) que incluso no son de la mejor calidad (digamos 3MB/cada) toman unos cientos de megabytes de RAM, incluso si los codigo en JPEG y la tienda ellos después de eso. Y me gustaría trabajar con 100 imágenes o más. – supo

+0

Hmm espere un segundo, ahora vi que está creando un archivo allí. ¿No está creado createTempFile en AIR? No lo mencioné, pero esta no es una aplicación de AIR. – supo

1

Estoy pensando que la operación está completamente prohibida, por buenas razones. Si puede duplicar una nueva FileReference a través del código ActionScript, también podrá fabricar un objeto FileReference a través del código ActionScript. Por supuesto, sería un agujero de seguridad bastante malo si pudieras forzar la carga de un archivo arbitrario.

Mantener una copia de los datos en la memoria realmente no es tan malo como una solución. Después de todo, es temporal. La computadora cliente típica debería poder administrar unos cientos de MB extra de datos sin ningún problema. Sin duda es una mejor opción que hacer que su navegador haga dos cargas por separado, que es lo que su intento de solución terminaría haciendo.

Una solución potencial completamente diferente a este problema es evitar la manipulación de imágenes por parte de Flex. Flex podría publicar el archivo cargado directamente en el servidor, y el servidor podría hacer la manipulación de la imagen. Por supuesto, si la manipulación se lleva a cabo a través de las interacciones del usuario, entonces eso no funcionaría en absoluto.

+0

¿Algunos cientos de MB adicionales? AFAIK no hay forma de que pueda almacenar 1 foto en menos de 50 MB de RAM. Estas imágenes son jpegs y pesan alrededor de 1-5MB cuando están comprimidas en el disco. Me gustaría trabajar con 100 imágenes como mínimo, lo que hace que sea de 5 GB de RAM, lo cual no es aceptable de ninguna manera. La otra alternativa que sugieres me ocurrió a mí también. La manipulación no es conducida por el usuario, PERO este enfoque requeriría que el usuario espere hasta que todas las imágenes se carguen en buena calidad y esto puede tomar como una hora. No quiero obligar al usuario a esperar tanto tiempo al comienzo de su trabajo con la aplicación. – supo

+0

Si puede sugerir una manera CÓMO almacenar las imágenes en RAM de manera más eficiente, eso sería genial. Hasta ahora probé bitmaps básicos que es estúpido y luego traté de codificarlos en Jpeg y almacenarlos como bytes. – supo

+0

No tendría que almacenar todos los cientos de imágenes a la vez. Puede procesarlos uno a la vez, liberando el búfer temporal después de terminar con cada uno. – Jacob

1

Estaba tratando de hacer casi exactamente lo que estaba haciendo, y casi me rindo después de leer algunas de las respuestas, pero creo que encontré la manera de hacerlo.Descubrí que si tiene un objeto FileReference, si llama al load() varias veces, funcionará, pero el problema principal es que mantiene los bytes de alta resolución en la memoria después de la primera carga. Como mencionó, para las personas que no conocen el procesamiento de imágenes, este es un gran no-no.

La forma de evitar esto es que después de su primer load(), necesita llamar al método cancel() en FileReference. Desde mi prueba hasta ahora, parece que va a borrar los bytes en FileReference, y load() seguirá funcionando si lo llamas por segunda vez más tarde. Hasta ahora, solo lo he probado en mi sistema, pero funciona bien allí. Solo una advertencia, este no es un comportamiento explícitamente definido en la API, por lo que definitivamente está sujeto a cambios, pero puede ayudarlo a llegar a donde necesita ir mientras tanto.

Espero que ayude.