C#使用字节数组中的标题分隔响应中的内容

时间:2017-07-16 00:34:52

标签: c# arrays string split gzip

如果在控制台中打印,我有一个字节数组:

HTTP/1.1 200 OK
Cache-Control: no-cache
Content-Length: 163
Content-Type: text/plain
Content-Encoding: gzip
Vary: Accept-Encoding
Server: Microsoft-IIS/8.0
Set-Cookie: ckperm=1498739450811
Set-Cookie: cknw=1498739582361
Set-Cookie: ckcd1=204510200
Set-Cookie: ckcd2=35132595069
X-Powered-By: ASP.NET
Date: Sun, 16 Jul 2017 00:27:57 GMT

      ??`I?%&/m?{J?J??t?`$??@???????iG#)?*??eVe]f@??????{????
{????;?N'????\fdl??J???!????~|?"?m?j??[????^?m6?V???l??}???????{?>?{?
3?????U-??.

内容高于打印时损坏的内容。我想删除标题,只获取将以byte[]形式返回的内容。将响应转换为字符串并用换行符拆分字符串不是一个选项,因为它已被破坏。我怎样才能做到这一点?谢谢!

2 个答案:

答案 0 :(得分:0)

要将您的 HTTP 请求标头和数据分开:

  1. 读取NetworkStream并将数据复制到MemoryStream
  2. 调用 byte[] mem = MemoryStream.ToArry() 方法
  3. 搜索这些字节 { 13, 10, 13, 10 } 并找到 mem 内的第一个索引
  4. 和子串 membyte[] heaader = mem[..endpoint]
  5. 如果您想使用 Http 请求正文,您可能需要安装 nuget 包Install-Package HttpMultipartParser,您可以在 https://github.com/Http-Multipart-Data-Parser/Http-Multipart-Data-Parser 找到它的存储库立>

这是您需要的代码:

// This method will read HTTP Request
public async void ReadRequestHeader(NetworkStream stream) 
{
    MemoryStream memory = new MemoryStream();
    
    while (stream.DataAvailable && stream.CanRead)
    {
          byte[] b = new byte[256];
          int read = await stream.ReadAsync(b, 0, b.Length);
          await memory.WriteAsync(b, 0, read);
    }
    
    memory.Seek(0, SeekOrigin.Begin);
    byte[] mem = memory.ToArray();
    byte[] emptyline = new byte[] { 13, 10, 13, 10 };

    byte[] data;
    byte[] header;
    bool test = mem.Contains(emptyline, out int endpoint);
    if (test)
    {
         endpoint+= emptyline.Length;
         header = mem[..endpoint]; // your Header bytes
         data = mem[endpoint..];   // your Body bytes

         // if you want to consume http request body. just follow
         MultipartFormDataParser parser = await MultipartFormDataParser.ParseAsync(new MemoryStream(data)).ConfigureAwait(false);
         Console.WriteLine("MyName : {0}", parser.GetParameterValue("username"));
         foreach (FilePart file in parser.Files)
         {
             File.WriteAllBytes(   
    Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), file.FileName), ((MemoryStream)file.Data).ToArray()
);

          }


    }
}

现在,让我们实施 Contains(this byte[] self, byte[] candidate, out int ep)

// Note: I've copied this class from
// https://stackoverflow.com/a/5062250/10903225

    static class ByteArrayRocks
    {

        public static bool Contains(this byte[] self, byte[] candidate, out int ep)
        {
            ep = 0;
            if (IsEmptyLocate(self, candidate))
                return false;

            for (int i = 0; i < self.Length; i++)
            {
                if (IsMatch(self, i, candidate))
                {
                    ep = i;
                    return true;
                }
            }

            return false;
        }

        static bool IsMatch(byte[] array, int position, byte[] candidate)
        {
            if (candidate.Length > (array.Length - position))
                return false;

            for (int i = 0; i < candidate.Length; i++)
                if (array[position + i] != candidate[i])
                    return false;

            return true;
        }

        static bool IsEmptyLocate(byte[] array, byte[] candidate)
        {
            return array == null
                    || candidate == null
                    || array.Length == 0
                    || candidate.Length == 0
                    || candidate.Length > array.Length;
        }
    }

注意: 我知道这不是最好的解决方案,特别是如果 Http 请求主体太大(这会占用你所有的内存)。但是,您可以指定 MemoryStream

要读取的固定字节数

我希望这个冗长的解决方案对您有所帮助。

答案 1 :(得分:-1)

以下是标题中的重要信息:

  

内容编码:gzip

您看到的是gzip数据。你需要解压缩它。