6

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

顺便问一下,为什么叫解压?这听起来对我来说很可怕,我一直以为它会减压......

4

3 回答 3

4

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

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

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

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

于 2009-05-30T13:54:32.003 回答
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 to /dev/null 的建议是合理的。
如果您要上传 .zip 文件,它包含一个目录,该目录会告诉您文件未压缩时的大小。再次,此信息被内置到文件格式中,尽管这受恶意客户端的影响。

于 2009-05-30T15:30:49.937 回答
3

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

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

于 2009-05-30T15:19:17.963 回答