GZIP 文件已损坏 - 但为什么呢?
GZIP File corrupted - but why?
我目前正在研究 GZIP HTTP 解压缩。
我的服务器接收到一些数据并以二进制模式裁剪和保存。
我制作了一个小脚本来从 Whosebug 下载 gzip 并将其保存到 .gz 文件中。
工作正常!
但是我从 fortigate-firewall 收到的“gzip”最终被损坏了。
这里有损坏的工作文件:https://gofile.io/d/j520Nr
缓冲区是损坏的文件 - 我不确定为什么。
这两个文件截然不同(至少我是这样看的)- 但 GZIP header 肯定存在!
有人可以比较这两个文件并告诉我为什么它们如此不同吗?
或者甚至可以告诉我如何修复它?
这就是两个文件的 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");
如前所述,分块和缓冲区大小在这里发挥了重要作用。
请记住,ICAP 使用分块,因此您必须使用 CONTINUE 响应前一个包,否则您只会从服务器接收前 X 个字节。
我目前正在研究 GZIP HTTP 解压缩。
我的服务器接收到一些数据并以二进制模式裁剪和保存。 我制作了一个小脚本来从 Whosebug 下载 gzip 并将其保存到 .gz 文件中。 工作正常!
但是我从 fortigate-firewall 收到的“gzip”最终被损坏了。
这里有损坏的工作文件:https://gofile.io/d/j520Nr
缓冲区是损坏的文件 - 我不确定为什么。 这两个文件截然不同(至少我是这样看的)- 但 GZIP header 肯定存在!
有人可以比较这两个文件并告诉我为什么它们如此不同吗? 或者甚至可以告诉我如何修复它?
这就是两个文件的 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");
如前所述,分块和缓冲区大小在这里发挥了重要作用。
请记住,ICAP 使用分块,因此您必须使用 CONTINUE 响应前一个包,否则您只会从服务器接收前 X 个字节。