【问题标题】:GZIP File corrupted - but why?GZIP 文件已损坏 - 但为什么?
【发布时间】:2020-09-19 16:14:39
【问题描述】:

我目前正在研究 GZIP HTTP 解压缩。

我的服务器接收到一些数据,我将其裁剪并以二进制模式保存。 我制作了一个小脚本来从 stackoverflow 下载 gzip 并将其保存到 .gz 文件中。 工作正常!

但是我从我的 fortigate-firewall 收到的“gzip”最终被损坏了。

此处已损坏且仍在工作的文件:https://gofile.io/d/j520Nr

缓冲区是损坏的文件 - 我不知道为什么。 这两个文件非常不同(至少我是这么看的)——但 GZIP 标头肯定存在!

有人可以比较这两个文件并告诉我为什么它们如此不同吗? 或者甚至可以告诉我如何解决它?

这是两个文件的 gzip html url:What is the best way to parse html in C#?

我损坏的文件大约大 2KB!

我会为朝着正确方向迈出的每一步感到高兴 - 也许它可以很容易地解决!

以下代码应该向您展示我的工作流程,“ReadAll”非常慢,但从流中读取所有内容。会优化ofc(可能是gzip流错误的问题?)

    public static byte[] ReadAll(NetworkStream stream, int buffer)
    {
        byte[] data = new byte[buffer];
        using MemoryStream ms = new MemoryStream();
        int numBytesRead;
        while ((numBytesRead = stream.Read(data, 0, data.Length)) > 0)
        {
            ms.Write(data, 0, numBytesRead);
        }
        return ms.ToArray();
    }

    private bool Handled = false;

    /// <summary>
    /// Handles Client and passes matches to the parser for more investigation
    /// </summary>
    /// <param name="obj"></param>
    private void HandleClient(object obj)
    {
        TcpClient client = (TcpClient)obj;
        Out.Log(LogLevel.Verbose, $"Client {client.Client.RemoteEndPoint} connected");
        Data = null; // Resets data after each received stream
        // Get a stream object for reading and writing
        NetworkStream stream = client.GetStream();
        //MemoryStream memory = new MemoryStream();

        // Wait to receive all the data sent by the client.
        if (stream.CanRead)
        {

            Out.Log(LogLevel.Debug, "Can read stream");
            StringBuilder c_completeMessage = new StringBuilder();

            if (!Handled)
            {
                Out.Log(LogLevel.Warning, "Handling first and last client.");
                Handled = true;
                int breakPoint = 0;
                byte[] res = ReadAll(stream, 1024);
                for (int i = 0; i < res.Length; i++)
                {
                    int xy = res[i];
                    int yy = res[i + 1];
                    if (res[i].Equals(31) && res[i + 1].Equals(139))
                    {
                        breakPoint = i;
                        Out.Log(LogLevel.Error, GZIP_MAGIC + $" found. Magic Number of GZIP at :{breakPoint}:");
                        break;
                    }
                    continue;
                }

                byte[] res2 = res.SubArray(breakPoint, res.Length - breakPoint - 7); // (7 for offset linebreaks, eol, etc)
                res2.WriteToFile(@"C:\Users\--\Temporary\Buffer_ReadFully_cropped.gz");

【问题讨论】:

  • 我们可以看一些代码吗?目前还不清楚问题出在哪里
  • 我没有看到任何与 gzip 相关的代码。 2kb 看起来像两个缓冲区。如果您设置缓冲区大小,例如到8192?如果是,你有一些意想不到的 EOF。顺便说一句,strem 可能不仅包含文件,还包含诸如 url 编码形式之类的东西。目前尚不清楚文件是如何发送的以及正在使用什么协议。
  • 其实!这是缓冲区的问题......有点。分块是我的问题。小型网站可以完美加载,而像 stackoverflow 这样的大型网站会导致 gzip 流损坏,因为它们不完整!感谢您的提示:)!

标签: c# stream compression gzip deflate


【解决方案1】:

如前所述,分块和缓冲区大小在这里发挥了重要作用。

请记住,ICAP 使用分块,因此您必须使用 CONTINUE 响应前一个包,否则您只会从服务器收到前 X 个字节。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-04-18
    • 1970-01-01
    • 2019-11-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多