获取zlib中未压缩数据的大小?

时间:2009-05-30 13:50:37

标签: php c compression size zlib

我正在创建包含各种文件上传服务的东西,我需要存储使用zlib的compress()函数压缩的数据。我通过互联网发送它已经压缩,但我需要知道远程服务器上未压缩的文件大小。有没有办法在没有首先解压缩服务器上的数据的情况下找出这些信息,只是为了提高效率?这就是我现在正在做的事情,但如果有一条捷径,我很乐意接受它。

顺便问一下,为什么称它为uncompress?这对我来说听起来很糟糕,我一直以为它会解压缩......

3 个答案:

答案 0 :(得分:4)

我对此表示怀疑。我不相信这是底层zlib库从内存中提供的东西(虽然自从我使用它以来已经好了7年或8年,但最新的文档似乎并未表明此功能已被添加)。

一种可能性是转移包含未压缩大小的另一个文件(例如,同时转移file.zipfile.zip.size),但这似乎充满了危险,特别是如果你的大小错误。

另一种选择是,如果服务器解压缩时间很长但不必立即完成,则可以在优先级较低的后台任务中执行(如Linux下的nice)。但同样,如果尺寸检查器开始运行(可能会有太多上传),则可能存在缺陷。

我倾向于用“爆炸性减压”来考虑减压,而不是一个好用的术语: - )

答案 1 :(得分:4)

如果您使用原始“压缩”格式上传,则您将无法获得有关正在上传的数据大小的信息。 Pax在这方面是正确的。
您可以在压缩缓冲区的开头将其存储为4字节标头 - 假设文件大小不超过4GB 一些C代码作为例子:

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

然后发送大小为compressedSize + sizeof(uLongf)的完整compressBuffer。当您在服务器端收到它时,您可以使用以下代码来获取数据:

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

如果您不信任客户端发送正确的大小,那么您将需要对服务器大小执行某种未压缩的数据检查。使用uncompress到/ dev / null的建议是合理的 如果您要上传.zip文件,它会包含一个目录,告诉您文件未压缩时的大小。此信息内置于文件格式中,尽管这受到恶意客户端的影响。

答案 2 :(得分:3)

zlib格式没有原始输入大小的字段,因此我怀疑如果不模拟数据的解压缩,您将能够做到这一点。 gzip format有一个“输入大小”(ISIZE)字段,您可以使用,但是您可能希望避免更改压缩格式或让客户端发送文件大小。

但即使你使用不同的格式,如果你不信任客户端,你仍然需要运行更昂贵的检查,以确保未压缩的数据是客户端所说的大小。在这种情况下,您可以做的是使 uncompress-to-/ dev / null 进程更便宜,确保zlib不会在任何地方写入输出数据,因为您只想知道未压缩的尺寸。