2009-05-30 7 views
5

Estoy creando algo que incluye un tipo de servicio de carga de archivos, y necesito almacenar datos comprimidos con la función compress de zlib. Lo envío a través de Internet ya comprimido, pero necesito saber el tamaño del archivo descomprimido en el servidor remoto. ¿Hay alguna manera de que pueda descifrar esta información sin descomprimir los datos en el servidor primero, solo por eficiencia? Así es como lo estoy haciendo ahora, pero si hay un atajo, me encantaría tomarlo.Obtener el tamaño de los datos sin comprimir en zlib?

Por cierto, ¿por qué se llama descomprimir? Eso suena bastante terrible para mí, siempre pensé que sería descomprimir ...

+1

Mi suposición de por qué se llama uncompress se debe a un programa llamado pkzip que apareció a principios de los 90. Hubo un programa simular llamado pkunzip. Creo que la "ONU" se quedó. http://en.wikipedia.org/wiki/PKZIP – gradbot

+0

Más investigaciones en wikipedia sugieren que fue una demanda que forzó un cambio de nombre. "Katz cambió los nombres de sus utilidades a PKPAK y PKUNPAK". Más tarde crearon su propia versión llamada zip. "El nombre" zip "(que significa" velocidad ") fue sugerido por el amigo de Katz, Robert Mahoney. Querían dar a entender que su producto sería más rápido que ARC y otros formatos de compresión de la época". De ahí nació zip y descomprimir. – gradbot

+0

Ah-hah. Interesante :) – AriX

Respuesta

3

El formato zlib no tiene un campo para el tamaño de entrada original, por lo dudo usted podrá hacer eso sin simular una descompresión de los datos. El gzip format tiene un campo de "tamaño de entrada" (ISIZE), que podría usar, pero tal vez desee evitar cambiar el formato de compresión o hacer que los clientes envíen el tamaño del archivo.

Pero incluso si utiliza un formato diferente, si no confía en los clientes, aún deberá ejecutar una comprobación más costosa para asegurarse de que los datos no comprimidos son del tamaño que el cliente dice que es. En este caso, lo que puede hacer es hacer que el proceso uncompress-to-/dev/null sea menos costoso, asegurándose de que zlib no escriba los datos de salida en ningún lugar, ya que solo quiere saber el tamaño sin comprimir.

+0

Gracias. No había pensado en descomprimir en/dev/null :) – AriX

4

Lo dudo. No creo que esto sea algo que las bibliotecas zlib subyacentes ofrecen desde la memoria (aunque han pasado unos buenos 7 u 8 años desde que lo usé, los documentos actualizados no parecen indicar que se haya agregado esta característica).

Una posibilidad sería transferir otro archivo que contenga el tamaño sin comprimir (por ejemplo, transferir file.zip y file.zip.size) pero parece peligroso, especialmente si el tamaño es incorrecto.

Otra alternativa es, si el descompresión del servidor es costoso en el tiempo pero no tiene que hacerse inmediatamente, hacerlo en una tarea de segundo plano de baja prioridad (como con nice en Linux). Pero, de nuevo, puede haber inconvenientes si el verificador de tamaños comienza a correr hacia atrás (hay muchas cargas entrando).

Y tiendo a pensar en la descompresión en términos de "descompresión explosiva", no es un buen término para usar :-)

+0

Sí, siempre podría decirle al servidor cuál es el tamaño, pero los usuarios podrían explotar esto fácilmente, y realmente no quiero hacer algún tipo de comprobación de hash complicada ni nada. – AriX

3

Si carga con el formato raw 'compress', no tendrá información sobre el tamaño de los datos que se cargan. Pax es correcto en este sentido.
Puede almacenarlo como un encabezado de 4 bytes al comienzo del búfer de compresión, suponiendo que el tamaño del archivo no supere los 4 GB.
algo de código C como ejemplo:

uint8_t *compressBuffer = calloc(bufsize + sizeof (uLongf), 0); 
uLongf compressedSize = bufsize; 
*((uLongf *)compressBuffer) = filesize; 
compress(compressBuffer + sizeof (uLongf), &compressedSize, sourceBuffer, bufsize); 

a continuación, enviar el compressBuffer completo del tamaño compressedSize + sizeof (uLongf). Cuando lo reciba en el lado del servidor se puede utilizar el siguiente código para obtener los datos de nuevo:

// data is in compressBuffer, assume you already know compressed size. 
uLongf originalSize = *((uLongf *)compressBuffer); 
uint8_t *realCompressBuffer = compressBuffer + sizeof (uLongf); 

Si usted no confía en que el cliente envíe el tamaño correcto, entonces tendrá que realizar algún tipo de sin comprimir verificación de datos en el tamaño del servidor. La sugerencia de usar descompresión para/dev/null es razonable.
Si está cargando un archivo .zip, contiene un directorio que le dice el tamaño del archivo cuando está descomprimido. Esta información está incorporada en el formato de archivo, una vez más, aunque está sujeta a clientes malintencionados.

Cuestiones relacionadas